我刚开始学习c++,并试图了解智能指针。显然,下面的代码会崩溃(我想这是因为赋值创建了shared_ptr的副本)。是否有一种方法可以通过在ptrs[3]
上调用某种set方法来保持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.
您似乎认为这样做:
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 );
与shared_ptr
和其他东西无关,您的所有代码归结为:
int a = 0;
int b = a;
a = 42;
// why b isn't == to 42?
好好想想……恐怕这就是我所能提供的答案了。
请不要犹豫,我很乐意回答,但在你这样做之前请再考虑一下