类存储对unique_ptr的引用的最佳/最直观的方式是什么



我有一个类管理unique_ptr的向量:

class Foo
{
public:
...
private:
std::vector<std::unique_ptr<SomeClass>> vec_;
};

我有另一个类Bar,我想存储一些引用类型,引用向量中的对象。实现这一点的最合乎逻辑和最直观的方法是什么?

我能想到的有四种选择:

Bar存储引用

struct Bar
{
Bar(std::unique_ptr<SomeClass>& ref) : ref_(ref) {}
std::unique_ptr<SomeClass>& ref_;
};

这很简单,但是如果不重新构造对象,就无法重置引用。这仍然是首选方法吗?

FooBar中同时使用shared_ptr

class Foo
{
public:
...
private:
std::vector<std::shared_ptr<SomeClass>> vec_;
};
struct Bar
{
std::shared_ptr<SomeClass> ref_;
};

这个问题在于,它意味着FooBar对对象具有相等的所有权,即使Foo应该具有所有权。但也许这没什么大不了的?我犹豫的原因是我读到只有在所有权真正平等的情况下才应该使用shared_ptr。我还知道,与unique_ptr相比,shared_ptr带来了相当大的开销。

使用weak_ptr来表明Bar没有对象的所有权(但是,强制您在Foo中仍然使用shared_ptr(

struct Bar
{
std::weak_ptr<SomeClass> ref_;
};

对我来说,这是一个很好的方法。我能看到的唯一缺陷是,即使Foo拥有唯一所有权,我们也必须在Foo中使用shared_ptr

使用unique_ptr::get获取Bar存储的原始指针

struct Bar
{
SomeClass* ref_;
}

这是我最不喜欢的选择。我们使用智能指针的全部原因是为了避免使用原始指针。把它们用于引用智能指针这样简单的事情感觉很傻。

当考虑到性能和代码可维护性时,这些选项中的哪一个是首选的,还是主观的?

我们使用智能指针的全部原因是为了避免使用原始指针

否:我们使用智能指针的全部原因是为了避免使用拥有原始指针的

请参阅C++核心指南:以供参考

R.3:一个原始指针(一个T*(是非拥有的

我们确实更喜欢智能指针来表示自己的资源。但是,它并不拥有资源,所以使用原始指针是可以的。

从最差到最好的选择:

  1. Bar存储引用:如果您想重新放置它,请不要使用引用。你说你确实想重新密封它,所以这就结束了。尝试解决这个问题没有任何好处,它只会让你的代码更加令人惊讶,也不会更好。

  2. 在这两个位置都使用shared_ptr:如果您需要对象保持活动状态,只要存在对它的引用,就可以这样做。

    不要担心"平等所有权";,担心语义是否对您的程序有意义。你的工作是决定在Foo::vec_中重置指针是否应该破坏对象,而不是在C++中表达共产主义宣言。

  3. 使用shared_ptrweak_ptr:如果希望Bar检测到对象已被销毁。

    优点是它很好地记录了关系,并且您不必担心在更新FooBar之间意外访问悬挂指针。

拥有一个非拥有的原始指针是完全可以的,只要你确信一旦它不再有效,你不会意外地取消引用。话虽如此,shared_ptr的开销主要发生在构造函数和析构函数调用期间(+使用过的内存中的一些小开销,因为需要为通过shared_ptr拥有的每个对象分配一个额外的控制块(,因此,只要你不关心内存的每一个字节,也不在任何地方按值传递shared_ptrs,你就不太可能注意到任何显著的性能差异——因此,拥有对象的shared_ptr和用于存储引用的weak_ptr可能是一种更安全、更好的方法。

相关内容

  • 没有找到相关文章

最新更新