• Advertisement
Sign in to follow this  

Quick help on const

This topic is 714 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys,

 

I have this code, and I want to try to explain myself about it.

I decided to post here cause I'm not sure if I am right, and I need your help to convince me. Here goes:

const NodeList& const getChildren() const { return _children; }

How I read it:
- getChildren() will not allow changes of the instance including its members.

- It returns a constant reference of a constant NodeList (NodeList is std::vector<Node>), which means nobody should be able to modify the return value nor the reference.

 

My goal on this code is, I want to return a private _children where everyone can only modify its values, but not the _children itself.

 

Am I doing this right? if yes, is there something else in detail can be explained here? if no, what do I miss?

Share this post


Link to post
Share on other sites
Advertisement

Alright folks! gonna use const Node* getChild(int index) const for now instead of getChildren() to get the whole thing. I literally have no use of it for iteration whatsoever outside itself anyway.

 

Now I also changed the vector to contain it with Node*. Just need to control these on my own cause there will be hundreds of them scattered around and I don't want it popping in and out from the stack (I wonder if I'm right). But I guess that's a different topic. Anyway thanks!

Edited by Alectora

Share this post


Link to post
Share on other sites

Alright folks! gonna use const Node* getChild(int index) const for now instead of getChildren() to get the whole thing. I literally have no use of it for iteration whatsoever outside itself anyway.


That isn't going to get you what you want. This returns a pointer to a const Node. The pointer will be mutable, but the Node itself won't be. You won't be able to modify the returned Node as you desire without removing the constness. const-correctness also won't allow this to be a const method in this case. If you want to modify something in an object through a method, that method must be non-const.

This is why I suggested returning a non-const reference or pointer above. ;) Edited by Oberon_Command

Share this post


Link to post
Share on other sites

Alright folks! gonna use const Node* getChild(int index) const for now instead of getChildren() to get the whole thing.

 
Might I suggest what you really want is Node const& operator[](int index) const?

 

It means you can not modify the value held by your object, but you can copy it if you need to.

 

If you really want callers to be able to modify data aggregated in your object, you could try using object-oriented architecture and instead have your object modifiy its own data.

Share this post


Link to post
Share on other sites

Alright folks! gonna use const Node* getChild(int index) const for now instead of getChildren() to get the whole thing. I literally have no use of it for iteration whatsoever outside itself anyway.

 
As Oberon_Command said, that means you won't be able to edit the child.
 
Normally what is done in these situations, is to provide two functions:

const Node* getChild(int index) const   //Called when the class is const (as accessed through whatever variable you are using to call the function)
      Node* getChild(int index)         //Called when the class isn't const

That way, when you do something like this:

MyClass myClass;

Node *node = myClass.getChild(12); //Calls the non-const version of the function, which returns a non-const node.
if(node) node->setValue("meow");   //And we can read or write to non-const nodes.

...you can change the node's values.
 
Same thing if you are using a non-const reference or pointer:

MyClass &myClassRef = myClass;
Node *node = myClassRef.getChild(12);
if(node) node->setValue("meow");

But when you are trying to access the function through a const variable or const reference, it prevents writing:

const MyClass &constRef = myClass;
const Node *node = constRef.getChild(12); //Calls the const version of the function, which returns a const node pointer.
if(node)
{
    node->setValue("meow"); //Properly fails to compile, since we don't want to allow editing of const classes.
    node->getValue();       //We can still read from the class though.
}

And if you do need iteration, you can just create begin() / end() functions in the class yourself, by exposing the internal container's begin() / end().
 
If you're using a modern C++14 compiler, it's as easy as:

class MyClass
{
public:
    auto begin()       { return children.begin(); }
    auto begin() const { return children.begin(); } //We want const and non-const iteration to be available.
    auto end()         { return children.end();   }
    auto end() const   { return children.end();   }
};

Note: If you are using an older compiler (C++11 or C++03), it's still easy to do, it just requires a smidgen more boilerplate code.

Share this post


Link to post
Share on other sites

Yeah I've corrected the const. Tested it before and it didn't work so I removed them. Dang, I'm super noob.  :P

At least It's good for me to know how these const works on the code I provided in the end.

 

Anyway Oberon gave me a good suggestion on returning the child right away in a function so I guess the case changes. It's definitely fine if only the Node itself being modified.

 

And I guess I'm fine without exposing the begin and end yet, but thanks for the details.

 

Do you really need a vector of pointers? What do you mean by, "popping in and out from the stack"?

 

Hmm, I was thinking that I'd rather have the child nodes in the heap instead of the stack so I can control them manually? I don't want them to be destroyed immediately unless I tell them so, which I guess that's what will happen if I put in the stack and they went out of scope or erased/removed? and there will hundreds of nodes allocated, and I don't want to mess with the stack memory for this one? Please correct this lost soul if he's mistaken.  :wacko:

 

Might I suggest what you really want is Node const& operator[](int index) const?

 

It means you can not modify the value held by your object, but you can copy it if you need to.

 

If you really want callers to be able to modify data aggregated in your object, you could try using object-oriented architecture and instead have your object modifiy its own data.

 

Hmm, good suggestion, I'll check it out.  :D

Edited by Alectora

Share this post


Link to post
Share on other sites

 

Do you really need a vector of pointers? What do you mean by, "popping in and out from the stack"?

 
Hmm, I was thinking that I'd rather have the child nodes in the heap instead of the stack so I can control them manually? I don't want them to be destroyed immediately unless I tell them so, which I guess that's what will happen if I put in the stack and they went out of scope or erased/removed? and there will hundreds of nodes allocated, and I don't want to mess with the stack memory for this one? Please correct this lost soul if he's mistaken.  :wacko:

 

 

It sounds like you're getting ahead of yourself a bit. Vector allocation is already on the heap, but I don't think this is a heap/stack issue. It sounds like you want to do something unusual with lifetime management. If the 'node' is a POD then just use vector without pointers. The indirection you're introducing here is going to make iterating the vector very costly for no reason. It sounds like these objects have destructors though? I kind of want to know what's going on here, but even in that case you'd probably be better off doing manual mark and sweep if you need delayed destruction (why?).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement