c++11新特性,正确使用shared_ptr

New to c++11 features, proper use of shared_ptr?

本文关键字:shared ptr 新特性 c++11      更新时间:2023-10-16

所以我的理解是,当对象的最后一个剩余所有者被销毁或重新分配时,shared_ptr会自动从内存中解除分配,(这似乎太好了,不可能是真的吗?)当许多实例可能共享同一个对象时,这很有用。对的

所以在我的情况下,我正在制作一个2d平铺的世界,所以我在屏幕上绘制了许多相同的纹理。

我有

std::map<int, shared_ptr<Tile>> Tiledb;

以存储所有瓷砖。这个想法是只加载一次纹理,然后我可以随心所欲地渲染它。然后游戏结束后,我打电话给

Tiledb.clear();

这会自动释放所有内存吗?我习惯于常规的指针,这看起来很神奇,坦率地说,太容易了。我错了吗?使用shared_ptrs有什么缺点吗?我只是惊讶于它的存在哈哈。

感谢提供任何信息。

。。。当许多实例可能共享同一个对象时,它非常有用。对的

不完全是。当许多实例可能拥有同一对象时,它非常有用。共享不足以证明使用std::shared_ptr是合理的,因为使用它肯定会有一些开销

当您创建动态资源时,您需要考虑所有权,即谁负责删除它?应该负责删除资源的对象应该使用某种智能指针(或容器)来管理资源。

如果只有一个对象负责决定何时必须删除资源,则使用std::unique_ptr。如果其他对象/函数需要共享对资源的访问权限,但永远不会负责删除该资源,则向它们传递引用指向资源的原始指针

使用std::shared_ptr的时候,您不知道哪些共享资源的对象将是需要删除它的对象。在这种情况下,每个对象都应该通过持有std::shared_ptr来持有资源所有权

即使多个对象通过std::shared_ptr共享所有权,它们仍然应该只将引用原始指针传递给不需要所有者权限的对象/函数。

随意传递std::stared_ptr循环(在不需要它们的地方)的另一个问题是,它们可能会遇到Java内存泄漏问题。也就是说,对象永远不会消亡,因为对它们的一些引用保留在软件中被遗忘的部分。它们会逐渐积累并吞噬你的记忆。

通常,您应该更喜欢将资源保存在容器中,如std::vectorstd::map:

std::map<int, Tile> Tiledb;

容器管理Tile的销毁,因此不需要智能指针

但是,如果您使用的是多态Tile对象,则需要使用指针存储它们。为此,首选std::unique_ptr:

// When the Tiles are no longer needed after the map is destroyed
std::map<int, std::unique_ptr<Tile>> Tiledb;

如果其他对象需要在后继续访问Tile对象映射被破坏,则std::shared_ptr可能是合适的:

// only when Tiles need to keep living after the map is destroyed.
std::map<int, std::shared_ptr<Tile>> Tiledb; 

当然
类类型有构造函数和析构函数
它们在实例化期间和变量生命周期结束时被隐式调用。

这个概念被称为RAII,它是智能指针用于自动内存管理的工具。

这取决于您的用例,但您也可以考虑使用唯一的指针:

#include <iostream>
#include <memory>
#include <map>
struct Foo{
Foo(){
std::cout << "constructn";
}
~Foo(){
std::cout << "destructn";
}
};
int main(){
std::map<int, std::unique_ptr<Foo>> m;
//prints construct 3 times
m.emplace(1,std::make_unique<Foo>());
m.emplace(2,std::make_unique<Foo>());
m.emplace(3,std::make_unique<Foo>());
//prints destruct 3 times
m.clear();
}