我刚开始使用C++并试图绕过智能指针。显然,以下代码将崩溃(我想是因为赋值创建了shared_ptr的副本?)。有没有一种方法可以通过在foo.Other上调用某种set方法来保持ptrs[3]更新?

class Foo
{
public:
    int X;
    std::shared_ptr<Foo> Other;

    Foo() : X(10) { }
};

int main()
{
    Foo foo;

    std::vector<std::shared_ptr<Foo>> ptrs(10);

    foo.Other = ptrs[3];

    std::shared_ptr<Foo> other = std::shared_ptr<Foo>(new Foo());
    ptrs[3] = other;

    std::cout << foo.Other->X << std::endl; // throws Access violation exception

    return 0;
}

编辑:
这是我得到的异常,因为它指向null:

最佳答案

您似乎对这样做的印象是:

foo.Other = ptrs[3];

在两个对象之间创建某种关系,因此,如果您更改其中一个,则另一个也会更改。

那不是shared_ptr的工作原理。它指向的事物是共享的,更改事物意味着所有指向它的指针都将看到更改后的值(因为只有一个值,该值由多个对象拥有),因此可以正常工作:
std::shared_ptr<int> p = std::make_shared<int>(1);
assert( *p == 1 );
std::shared_ptr<int> q = p;
*q = 2;
assert( *p == 1 );

但是shared_ptr对象本身并不都开始是彼此完全相同的副本。

他们指向同一件事,并不意味着他们是同一件事。

如果您将ptrs[3]更改为指向其他内容,则也不会使foo.Other指向其他内容。如果这样做会使shared_ptr几乎变得毫无用处,那么您将无法有效地拥有一个对象的多个所有者,因为一旦其中一个对象停止拥有该对象,所有其他对象也将立即停止拥有它,并且该对象将被销毁。

取而代之的是,只有您更新的shared_ptr会获得新值,其他shared_ptr保留其旧值。
std::shared_ptr<int> p = std::make_shared<int>(1);
assert( *p == 1 );
std::shared_ptr<int> q = p;
assert( *q == 1 );
assert( p == q );
assert( p.get() == q.get() );
assert( *p == *q );
p = std::make_shared<int>(2);
assert( *p == 2 );
assert( *q == 1 );
assert( p != q );
assert( p.get() != q.get() );
assert( *p != *q );

09-07 06:25