I have met a problem recently. I used vector
STL a lot in cocos2d-x. And in one of my class I wrote:
vector<StrokeDrawnode*> strokedrawList;
StrokeDrawnode
is inherited from CCNode
. However, I read some article said that it is better to use CCArray
to hold sub-class of CCObject
. Actually, I have problem with the memory management. I guess it is the problem. So my question is what situation should I use CCArray
and How can I deal with the memory management.
In what situation should I define the class member like this?
CC_SYNTHESIZE_RETAIN(CCSprite* , m_sprite_draw, Sprite);
The main difference between std::vector
and CCArray
in this case is that when you add objects to CCArray
they get retained. This is really important in cocos, as CCObject
-dervied (basically everything) objects get destroyed when their retainCount
reaches 0. This is done automatically between every frame.
Consider this example : Let's say you want to create 5 sprites and cache them for later use (they don't get to be on the screen until some time later in the future). Code (somewhere in the init()
method):
for(int i = 0; i < 5; ++i) {
CCSprite *vectorSprite = (...);
CCSprite *arraySprite = (...);
_vector.push_back(vectorSprite);
_array->addObject(arraySprite);
}
_array->retain(); // < ------- IMPORTANT!
// end of init method
We of course assume that _vector
and _array
are instance variables and don't get destroyed when init()
ends.
What does happen before the next frame is drawn is that all sprites we put into the _vector
will get destroyed - the vector will hold pointers to invalid memory locations.
Objects we put in _array
will not, because addObject
retains them for us. Notice that the _array
itself has to be retained as well, or it will be destroyed (I'm not sure about its contents).
Generally, I think it may be better to use cocos-containers
when working with cocos objects, as you only have to remember about retaining the container itself, and not all the objects. IF you really want to use std::vector
it may be plausible to subclass std::vector
so that its push_back
and pop_back
methods will retain
and realese
your objects respectively.
As to the macro - I have never used it, but it expands to this :
#define CC_SYNTHESIZE_RETAIN(varType, varName, funName) \
private: varType varName; \
public: virtual varType get##funName(void) const { return varName; } \
public: virtual void set##funName(varType var) \
{ \
if (varName != var) \
{ \
CC_SAFE_RETAIN(var); \
CC_SAFE_RELEASE(varName); \
varName = var; \
} \
}
Which creates a setter and a getter for your variable for outside use. In my opinion it seems only viable if you want to expose a variable to outside use and have this methods provided for you automatically. The added value here is of course the retain - release
process done in the setter.
Let me know if anything is not clear! Cheers.