【问题标题】:Setting std::shared_ptr source at a later stage在稍后阶段设置 std::shared_ptr 源
【发布时间】:2013-06-08 23:11:05
【问题描述】:

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

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:

Test.exe 中 0x01219AEF 的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000000。 Test.exe 中 0x01219AEF 处未处理的异常:0xC0000005:访问冲突读取位置 0x00000000。

【问题讨论】:

  • 您绝对应该做的一件事是使用std::make_shared 而不是std::shared_ptr&lt;Foo&gt;(new Foo())

标签: c++ shared-ptr smart-pointers


【解决方案1】:

您似乎认为这样做:

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_ptrs 保留其旧值。

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

【讨论】:

  • +1,这个 pointerpointed-to 的东西是如此“明显”,我什至没有想过要提及它,我的错。很好的解释顺便说一句。 :)
  • @syam 和 Jonathan:休息一下再看这个问题,我觉得自己很愚蠢。我的印象是我需要通过引用来传递指针,这以某种方式导致了这个奇怪的星座。再次感谢大家!
【解决方案2】:

shared_ptr 和其他内容无关,您的所有代码都归结为:

int a = 0;
int b = a;
a = 42;
// why b isn't == to 42?

想一想……恐怕我能提供的答案就这么多了。

不要犹豫,要求澄清,我很乐意回答,但在你这样做之前,请再考虑一下

【讨论】:

  • 感谢 syam,在这种情况下,b 应该只包含对 a 的引用,如果我们期望 b 等于 a。我会用我的例子来摆弄一下。
  • 好的,我会澄清一下:std::vector&lt;std::shared_ptr&lt;Foo&gt;&gt; ptrs(10); 创建一个包含 10 个空 shared_ptr 的向量。你将其中一个空的shared_ptr(我称之为a,你称之为ptrs[3])分配给foo.Other(我称之为b)。然后你更改a,并期望b 更改? ;) 这里没有引用,你只是在复制值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 2013-02-08
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多