使用Cocos2d-x处理游戏。我创建了CCLayers*
和许多CCSprites*
。我创建它们之后,在CCSprites
中添加了这些std::vector
。
我关注的是记忆和删除。
我试图围绕std::unique_ptr
。我的理解是,智能指针将有助于清理内存并防止泄漏。
但我不明白如何使用它。我是否每unique_ptr
个CCSPrite*
?我是否制作unique_ptr
并将整个矢量放入其中?
任何人都可以帮助我理解,并让我知道该怎么做?
答案 0 :(得分:2)
当前使用new
的任何地方,请确保结果立即转到unique_ptr或其reset()函数的ctor。而智能指针放置在需要的地方。或者您可以将受控对象提前传递给其他实例。或者使用reset()来核对它。
你通常不会用new分配的向量,所以它们不受智能指针的限制:向量本身管理内容的内存,你就是先行。
答案 1 :(得分:1)
如果您需要一个多态容器,这是一个可以容纳CCSprites或任何派生类的向量,那么您可以使用std::vector<std::unique_ptr<CCSprite>>
来描述它并为您提供对类的生命周期管理。
#include <memory>
#include <vector>
#include <iostream>
using namespace std;
class Foo {
int m_i;
public:
Foo(int i_) : m_i(i_) { cout << "Foo " << m_i << " ctor" << endl; }
~Foo() { cout << "Foo " << m_i << " ~tor" << endl; }
};
class FooBar : public Foo {
public:
FooBar(int i_) : Foo(i_) { cout << "FooBar " << m_i << " ctor" << endl; }
~FooBar() { cout << "FooBar " << m_i << " ~tor" << endl; }
};
int main(int argc, const char** argv) {
vector<unique_ptr<Foo>> foos;
Foo foo(1);
foos.emplace_back(unique_ptr<Foo>(new Foo(2)));
cout << "foos size at end: " << foos.size() << endl;
return 0;
}
(我尝试添加一个将短范围的unique_ptr添加到向量中的示例,但它导致我的GCC 4.7.3在测试时崩溃)
Foo 1 ctor
Foo 2 ctor
foos size at end: 1
[<-- exit happens here]
Foo 1 dtor
Foo 2 dtor
如果您不需要多态容器,那么只需让向量直接包含CCSprite对象就可以避免内存管理开销。这种方法的缺点是,如果添加/删除元素,给定精灵的地址可能会发生变化。如果对象不重要,这很快就会变得非常昂贵:
std::vector<CCSprite> sprites;
sprites.emplace_back(/* args */);
CCSprite* const first = &sprites.front();
for (size_t i = 0; i < 128; ++i) {
sprites.emplace_back(/* args */);
}
assert(first == &sprites.front()); // probably fires.
答案 2 :(得分:1)
简单unique_ptr<T>
是成员T* p
的包装类。在unique_ptr::~unique_ptr
中,它会调用delete p
。它有一个已删除的复制构造函数,因此您不会意外复制它(因此会导致双重删除)。
它还有一些功能,但基本上就是它。
如果您正在编写性能关键型游戏,那么使用某种内存池架构手动管理内存可能更好。这并不是说您不能使用vector<unique_ptr<T>>
作为其中的一部分,只是说您应该首先规划动态对象的生命周期,然后决定使用什么机制来删除它们。那一生的结束。
答案 3 :(得分:1)
Cocos2d-x对象有自己的引用计数器,它们使用自动释放池。如果您将使用std::unique_ptr
,则应手动从autorelease池中删除创建的对象,然后将其注册在unique_ptr中。更喜欢使用CCPointer
:https://github.com/ivzave/cocos2dx-ext/blob/master/CCPointer.h