这更像是一种造型而非性能问题。我刚刚转换(大部分)指向shared_ptr对象的指针,并且不情愿地接受weak_ptrs作为原始指针的替代品。我的问题是,迭代共享指针对象的序列(比如说一个向量)的首选方法是什么?这是我一直在做的事情:
std::vector<std::shared_ptr<A>> my_sequence;
// Do something to fill my_sequence;
for (std::shared_ptr<A> const& ptr : my_sequence)
{
ptr->AMethod();
}
这违反了*不要使用shared_ptr references *规则,那么什么是一个好的选择,为什么?
我会问的问题是;技术是否健全,即。对于AMethod()超小,my_sequence超大,这个方法会因shared_ptr副本而开始阻碍性能吗?它可读吗?这很简单吗?
答案 0 :(得分:8)
不使用shared_ptr引用的原因是因为你击败了它试图保护自己的机制。即有一个潜在的悬挂指针。如果您正在迭代容器,这应该不是问题,因为对象不会意外地消失在您身上。您不应该存储以后可能使用的shared_ptr引用。
即。这很糟糕:
struct Y
{
int y;
Y() : y(1) {}
};
struct X
{
shared_ptr<Y>& ref_shared_ptr_y;
X(shared_ptr<Y>& y) : ref_shared_ptr_y(y) {}
};
void main()
{
shared_ptr<Y> shared_ptr_y(new Y());
X x(shared_ptr_y);
y.reset();
x.ref_shared_ptr_y->y; // UB since x.ref_shared_ptr_y was deleted
}
只有在您确实需要在2个或更多位置之间共享对象所有权时,才应使用 shared_ptr
。否则会导致不必要的开销,并表明您并未真正考虑过所有者关系。如果您的所有权仅限于一个位置,请使用unique_ptr
。
答案 1 :(得分:6)
首先,免责声明:
shared_ptr
不是灵丹妙药。在实际共享所有权时应该使用它。非共享所有权由unique_ptr
表示,非所有权由(原始)引用表示。 weak_ptr
是shared_ptr
必须遵守但不归属的...... {但对于一般的过时指针来说,这不是一个很好的防御措施。默认为shared_ptr
直接导致最低的共同点;这是糟糕的编程习惯。
此处的选择介于shared_ptr< T >
,shared_ptr< T const >
,shared_ptr< T > const &
,T const &
和T &
之间。假设你没有改变任何东西,但序列可以改变它的对象,所以const
是可取的。这会将其缩小为shared_ptr< T const >
,shared_ptr< T > const &
和T const &
。
让我们将问题重新表述为,
shared_ptr< T > const &
是否是正确的选择?
从这个角度来看,评估替代方案。
shared_ptr< T const >
(按值传递共享指针)
shared_ptr< T >
move
d扩展所有权池const
正确性传播到被调用函数 shared_ptr< T > const &
(通过引用传递共享指针)
- :对被调用函数
失去const
正确性
shared_ptr< T const > const &
,则会传递临时副本,最终会遇到此替代方案和按值传递的缺点。- :对对象的访问通过额外的间接
T const &
(直接参考)
const
正确性权衡它,如果没有扩展所有权(例如通过返回保留参数的对象),你真的应该传递一个简单的引用。在这种情况下,函数应该很少关心它的参数是如何拥有的。要求shared_ptr
以最坏的方式违反关注点分离。您不能拥有本地对象或成员子对象,仍然可以使用该功能。最糟糕的是,一切都变得更加复杂。
如果所有权可能会扩展到其他人,这将是首先使用shared_ptr
的理由,那么您应该始终传递shared_ptr< [const] T >
值。是的,它会在通话时复制shared_ptr
。但复制shared_ptr
的昂贵部分是更新引用计数,而不是推送堆栈上的指针。如果您要授予所有权,则无论如何都要更新引用计数。获取传递的值move
,不触及引用计数。完成后,你没有任何优势和许多缺点,无法通过引用传递。