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

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

所以我的理解是,当对象的最后一个剩余所有者被销毁或重新分配时,shared_ptr 会自动从内存中释放,(似乎好得令人难以置信?)并且当许多实例可能是共享同一个对象。正确吗?

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

我有

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

存储所有的瓷砖。我的想法是只加载一次纹理,然后我可以根据需要多次渲染它。然后一旦游戏结束我打电话给

Tiledb.clear();

这会自动释放所有内存吗?我已经习惯了常规的指示,以至于这看起来很神奇,而且坦率地说,太容易了。我认为这就是它的工作原理是错误的吗?使用 shared_ptrs 有什么缺点吗?我只是很惊讶这存在哈哈。

感谢您提供任何信息。

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

这个概念被称为 RAII,智能指针利用它来进行自动内存管理。

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

#include <iostream>
#include <memory>
#include <map>

struct Foo{

  Foo(){
    std::cout << "construct\n";
  }

  ~Foo(){
    std::cout << "destruct\n";
  }
};

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();
}

...it's useful when many instances may be sharing the same object. Correct?

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

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

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

使用 std::shared_ptr 的时间是当您无法知道共享 资源的哪些对象将是需要删除它的对象时。在那种情况下,每个对象都应该通过持有 std::shared_ptr.

来持有资源的 所有权

即使多个对象通过 std::shared_ptr 共享 所有权 他们仍然应该只传递 reference原始指针指向objects/functions不需要所有权权利。

另一个问题是 std::stared_ptr 轮流随意(不需要它们的地方)是它们可能会遇到 Java 内存泄漏 问题.那就是对象永远不会消亡,因为对它们的一些引用仍然存在于软件的 forgotten 部分中。它们会逐渐积累并侵蚀你的记忆。

通常,您应该更喜欢将资源保存在 容器 中,例如 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 对象 之后 map 被销毁然后 std::shared_ptr 可能合适:

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