所以我的理解是,当对象的最后一个剩余所有者被销毁或重新分配时,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::vector
或std::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();
}