何时使用std::unique_ptr作为容器
When to use an std::unique_ptr as a container?
在Cocos2d-x中开发游戏。我有CCLayers*
和许多创建的CCSprites*
。在创建这些CCSprites
之后,我将它们添加到std::vector
中。
我关心的是记忆和删除。
我正试着把我的头缠在std::unique_ptr
上。我的理解是,智能指针将有助于清理内存并防止泄漏。
但是我不知道如何使用它。我会把每个CCSPrite*
都做成unique_ptr
吗?我做一个unique_ptr
并把我的整个向量放进去吗?
有人能帮我理解并告诉我该复习什么吗?
无论您当前在哪里使用new
,请确保结果立即转到unique_ptr的ctor或其reset()函数。智能指针被放置在需要的地方。或者,您可以将受控对象提前传递给另一个实例。或者使用reset()对其进行核攻击。
你通常不会用new来分配向量,所以它们不受智能指针控制:向量本身管理内容的内存,你领先于此。
unique_ptr<T>
是成员T* p
的包装类。在unique_ptr::~unique_ptr
中,它调用delete p
。它有一个已删除的复制构造函数,这样你就不会意外地复制它(从而导致双重删除)。
它还有一些更多的功能,但这基本上就是它的全部
如果您正在编写一款性能关键型游戏,那么最好使用某种内存池架构手动管理内存。这并不是说你不能使用vector<unique_ptr<T>>
作为其中的一部分,只是说你应该首先规划动态对象的生命周期,然后决定在生命周期结束时使用什么机制来删除它们。
Cocos2d-x对象有自己的引用计数器,它们使用自动释放池。如果要使用std::unique_ptr
,则应手动从自动发布池中删除创建的对象,然后将其注册到unique_ptr中。首选CCPointer
:https://github.com/ivzave/cocos2dx-ext/blob/master/CCPointer.h
如果您需要一个多态容器,即一个可以容纳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.
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- 引用 std::shared:ptr 以避免引用计数
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 使用std :: String ptr的错误打印std :: String
- C++中的大小释放:全局运算符delete的正确行为是什么(void*ptr,std::size_t size)
- std::哈希表示无序映射中的唯一 PTR
- boost::shared_ptr和std::shared-ptr的同居
- 我可以用std::shared_ptr而不是boost::shared-ptr构建boost库吗
- 正确使用std智能指针以确保ptr安全
- 如何创建 std::string 包装器,它将 ptr 保留为 std::string 和 ptr 到创建该包装器实例的
- 为什么 std::string{ "const char ptr" } 有效?
- 为什么 gcc 4.9.0 中没有定义"void operator delete(void* ptr, std::size_t size) noexcept;"?
- 在 std::map 的值中使用非 ptr 是一种很好的做法吗
- 共享 PTR - C++:std::shared_ptr<T> 和 std::shared_ptr<T const> 有什么区别?