2

在 Cocos2d-x 中开发游戏。我有CCLayers*,而且很多CCSprites*都是被创造出来的。CCSprites我在std::vector创建它们之后添加这些。

我关心的是记忆和删除。

我正试图绕过我的头std::unique_ptr。我的理解是智能指针将有助于清理内存并防止泄漏。

但我不明白如何使用它。我unique_ptr每个人都做CCSPrite*吗?我要制作一个unique_ptr并将整个向量放入其中吗?

任何人都可以帮助我理解并告诉我要复习的内容吗?

4

4 回答 4

2

无论您new当前在哪里使用,请确保结果立即转到 unique_ptr 的 ctor 或其 reset() 函数。并且该智能指针已放置,因此它将在需要的地方存在。或者您可以将受控对象传递给不同的实例。或者使用reset() 对其进行核对。

您通常不使用 new 分配的向量,因此它们不受智能指针的影响:向量本身管理内容的内存,您在这方面领先。

于 2013-06-23T20:20:48.960 回答
1

如果您需要一个多态容器,即可以容纳 CCSprite 或任何派生类的向量,那么您可以使用 astd::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.
于 2013-06-23T21:24:02.480 回答
1

简单地说unique_ptr<T>是一个成员的包装类T* p。在unique_ptr::~unique_ptr它调用delete p. 它有一个已删除的复制构造函数,因此您不会意外复制它(从而导致双重删除)。

它还有一些功能,但基本上就是这样。

如果您正在编写一个性能关键型游戏,那么使用某种内存池架构手动管理内存可能是一个更好的主意。这并不是说你不能使用 avector<unique_ptr<T>>作为其中的一部分,只是说你应该首先计划好动态对象的生命周期,然后决定在生命周期结束时使用什么机制来删除它们.

于 2013-06-23T21:38:50.163 回答
1

Cocos2d-x 对象有自己的引用计数器,它们使用自动释放池。如果你要使用std::unique_ptr,你应该手动从自动释放池中删除创建的对象,然后在 unique_ptr 中注册它。更喜欢使用CCPointerhttps ://github.com/ivzave/cocos2dx-ext/blob/master/CCPointer.h

于 2013-06-25T09:47:09.440 回答