class 存储对 unique_ptr 的引用的 best/most 直观方法是什么?
What is the best/most intuitive way for a class to store a reference to a unique_ptr?
我有一个 class 来管理 unique_ptr
s 的向量:
class Foo
{
public:
...
private:
std::vector<std::unique_ptr<SomeClass>> vec_;
};
我有另一个 class,Bar
,我想存储一些引用向量中的对象的引用类型。实现这一目标的最合乎逻辑和最直观的方法是什么?
我能想到的有四种:
Bar
存储引用
struct Bar
{
Bar(std::unique_ptr<SomeClass>& ref) : ref_(ref) {}
std::unique_ptr<SomeClass>& ref_;
};
这很简单,但是如果不重新构造对象就无法重置引用。这仍然是首选方法吗?
在 Foo
和 Bar
中都使用 shared_ptr
class Foo
{
public:
...
private:
std::vector<std::shared_ptr<SomeClass>> vec_;
};
struct Bar
{
std::shared_ptr<SomeClass> ref_;
};
这个问题是它暗示 Foo
和 Bar
对对象具有平等的所有权,即使 Foo
应该拥有所有权。但也许这没什么大不了的?我犹豫的原因是我读过,如果所有权确实相等,你应该只使用 shared_ptr
。我也知道 shared_ptr
与 unique_ptr
.
相比有相当多的开销
使用weak_ptr
表明Bar
没有对象的所有权(但是,迫使你仍然在Foo
中使用shared_ptr
)
struct Bar
{
std::weak_ptr<SomeClass> ref_;
};
对我来说,这似乎是一种干净利落的方法。我能看到的唯一缺陷是我们必须在 Foo
中使用 shared_ptr
,即使 Foo
拥有唯一所有权。
使用unique_ptr::get
获取Bar
存储
的原始指针
struct Bar
{
SomeClass* ref_;
}
这是我最不喜欢的选项。我们使用智能指针的全部原因是为了避免使用原始指针。将它们用于像引用智能指针这样简单的事情感觉很愚蠢。
在考虑性能和代码可维护性时,这些选项中的哪一个是首选,或者它是主观的?
The whole reason we use smart pointers is to avoid having to work with raw pointers
不:我们使用智能指针的全部原因是为了避免必须使用 拥有 原始指针。
R.3: A raw pointer (a T*) is non-owning
我们确实更喜欢智能指针来拥有资源。但是,它不拥有资源,因此使用原始指针没问题。
您的备选方案从最差到最好:
Bar 存储了一个参考:如果您想要重新安装它,请不要使用参考。你说你确实想要重新安装它,所以这已经结束了。尝试解决这个问题没有任何好处,它只会让您的代码更令人惊讶,而不是更好。
在两个地方都使用 shared_ptr
:如果您需要对象在存在引用的情况下保持活动状态,请执行此操作。
不要担心“平等所有权”,担心语义是否对你的程序有意义。你的工作是决定在Foo::vec_
中重置指针是否应该销毁对象,而不是在C++中表达共产主义宣言。
使用shared_ptr
加weak_ptr
:如果要Bar
检测到对象已经被销毁
优点是它很好地记录了关系,您不必担心在更新 Foo
和 Bar
之间意外访问悬空指针。
拥有一个非拥有的原始指针非常好,只要您确信一旦它不再有效就不会意外取消引用。
话虽如此,shared_ptr
的开销主要出现在构造函数和析构函数调用期间(+使用内存中的一些小开销,因为需要为每个通过 shared_ptr
拥有的对象分配一个额外的控制块),因此,只要您不关心内存的每个字节并且不在任何地方按值传递 shared_ptr
s,您就不太可能注意到任何显着的性能差异 - 因此具有 shared_ptr
拥有该对象和用于存储引用的 weak_ptr
可能是一种更安全、更好的方法。
我有一个 class 来管理 unique_ptr
s 的向量:
class Foo
{
public:
...
private:
std::vector<std::unique_ptr<SomeClass>> vec_;
};
我有另一个 class,Bar
,我想存储一些引用向量中的对象的引用类型。实现这一目标的最合乎逻辑和最直观的方法是什么?
我能想到的有四种:
Bar
存储引用
struct Bar
{
Bar(std::unique_ptr<SomeClass>& ref) : ref_(ref) {}
std::unique_ptr<SomeClass>& ref_;
};
这很简单,但是如果不重新构造对象就无法重置引用。这仍然是首选方法吗?
在 Foo
和 Bar
中都使用 shared_ptr
class Foo
{
public:
...
private:
std::vector<std::shared_ptr<SomeClass>> vec_;
};
struct Bar
{
std::shared_ptr<SomeClass> ref_;
};
这个问题是它暗示 Foo
和 Bar
对对象具有平等的所有权,即使 Foo
应该拥有所有权。但也许这没什么大不了的?我犹豫的原因是我读过,如果所有权确实相等,你应该只使用 shared_ptr
。我也知道 shared_ptr
与 unique_ptr
.
使用weak_ptr
表明Bar
没有对象的所有权(但是,迫使你仍然在Foo
中使用shared_ptr
)
struct Bar
{
std::weak_ptr<SomeClass> ref_;
};
对我来说,这似乎是一种干净利落的方法。我能看到的唯一缺陷是我们必须在 Foo
中使用 shared_ptr
,即使 Foo
拥有唯一所有权。
使用unique_ptr::get
获取Bar
存储
的原始指针
struct Bar
{
SomeClass* ref_;
}
这是我最不喜欢的选项。我们使用智能指针的全部原因是为了避免使用原始指针。将它们用于像引用智能指针这样简单的事情感觉很愚蠢。
在考虑性能和代码可维护性时,这些选项中的哪一个是首选,或者它是主观的?
The whole reason we use smart pointers is to avoid having to work with raw pointers
不:我们使用智能指针的全部原因是为了避免必须使用 拥有 原始指针。
R.3: A raw pointer (a T*) is non-owning
我们确实更喜欢智能指针来拥有资源。但是,它不拥有资源,因此使用原始指针没问题。
您的备选方案从最差到最好:
Bar 存储了一个参考:如果您想要重新安装它,请不要使用参考。你说你确实想要重新安装它,所以这已经结束了。尝试解决这个问题没有任何好处,它只会让您的代码更令人惊讶,而不是更好。
在两个地方都使用
shared_ptr
:如果您需要对象在存在引用的情况下保持活动状态,请执行此操作。不要担心“平等所有权”,担心语义是否对你的程序有意义。你的工作是决定在
Foo::vec_
中重置指针是否应该销毁对象,而不是在C++中表达共产主义宣言。使用
shared_ptr
加weak_ptr
:如果要Bar
检测到对象已经被销毁优点是它很好地记录了关系,您不必担心在更新
Foo
和Bar
之间意外访问悬空指针。
拥有一个非拥有的原始指针非常好,只要您确信一旦它不再有效就不会意外取消引用。
话虽如此,shared_ptr
的开销主要出现在构造函数和析构函数调用期间(+使用内存中的一些小开销,因为需要为每个通过 shared_ptr
拥有的对象分配一个额外的控制块),因此,只要您不关心内存的每个字节并且不在任何地方按值传递 shared_ptr
s,您就不太可能注意到任何显着的性能差异 - 因此具有 shared_ptr
拥有该对象和用于存储引用的 weak_ptr
可能是一种更安全、更好的方法。