This was … The most annoying this about migrating a project from cocos2dx 2.x to 3.0 is by far this problem, especially if you’re an average C++ programmer, like me…

Have a look here:

void setThingie(const std::vector<type>& other)
{
    _thingie = other;
}

...

std::vector<type> other;
setThingie(other);
other.push_back(something);

Do you see a problem above?

Here is the question:

We are passing the other vector by reference, that’s as clear as daylight. Then, we mutate it by adding an object. Does that effect the _thingie variable? … The answer is NO-da >.<

The previous containers used in cocos2d-x were all derived from CCObject, which meant you had to handle the memory management, as well as use pointers to pass things around. Switching to these objects made my design break.

In the game, I am creating a tree of possible paths, and each node contains a reference to the parent’s container, so it can see it’s “brothers”.

“Why not just give the child a pointer to the parent, and access the container through the parent?”

Of course, I would have done that… The issue is that the parent has four containers, and the child could be in any one of them. It’s as if the parent has 4 wives, and I am giving the child a pointer to the wife that gave birth to him!

In any case, with the issue above, the wife- I mean, the parent container was being mutated, but the child didn’t know! For example, the wife had a baby, so this child should know he has a brother.

// old code:
parent.containers = CCArray::create(4);
child.parentContainer = parent.containers[0];

// new code: BAD - Even by assigning a ref, it gets copied!
parent.containers = std::vector<Vector<Obj *>>(4);
// child.parentContainer is Vector<Obj *>
child.parentContainer = parent.containers[0];

// new code: GOOD - this finally solved it
parent.containers = std::vector<Vector<Obj *>>(4);
// child.parentContainer is const Vector<Obj *>*
child.parentContainer = &parent.containers[0];

This isn’t all diamonds and roses, it’s a very fragile design, unfortunately. By assigning a pointer, we risk having a dangling pointer when the parent goes away before the child, so we must make sure that never happens.