在一种情况下,shared_ptr会导致运行时错误,而在另一种情况下,则不会

Vir*_*ser 3 c++ pointers c++11

为什么

struct X{};

X x;
X *q = &x;
std::shared_ptr<X> p(&x);
Run Code Online (Sandbox Code Playgroud)

导致错误和

X x;
X *q = &x;
std::shared_ptr<X> p0 = std::make_shared<X>(x);
Run Code Online (Sandbox Code Playgroud)

不会导致运行时错误?

我读到在第一种情况下,我有“两个不同的指针,指向相同的数据,并且其中一个被共享”,

但是我认为在第二种情况下存在相同的情况?

运行时错误

free(): invalid pointer
Run Code Online (Sandbox Code Playgroud)

lub*_*bgr 10

在第一种情况下,x尽管对象的生命周期已在其作用域的结尾处结束,但该对象被删除。在这里,您可以在堆栈和范围内创建一个实例:

X x; // lifetime automatically ends at the end of the scope
Run Code Online (Sandbox Code Playgroud)

然后,您也要求std::shared_ptr控制的地址的生存期x

std::shared_ptr<X> p(&x); // calls delete at the end of the scope
Run Code Online (Sandbox Code Playgroud)

因此,您两次释放相同的变量,这是未定义的行为。在第二种情况下,您将创建一个std::shared_ptr独立于x实例的复制实例。

std::shared_ptr<X> p0 = std::make_shared<X>(x); // Copies x, then deletes the copy
Run Code Online (Sandbox Code Playgroud)

没问题,因为两个对象都只删除一次。

请注意std::make_shared此处的语义:传递给它的参数将转发到其模板参数的构造函数。因此,您将触发编译器生成的副本构造函数X(const X&)被调用。这与从std::shared_ptr已经存在的指针创建到via的方式非常不同std::shared_ptr p(&x);


Dav*_*rtz 7

在第一种情况下,p拥有的所有权x。当p超出范围时,它将删除x。但是x没有动态分配。哎呀。

在第二种情况下,您没有这种情况。该make_shared函数动态分配一个新的共享对象。当p0超出范围时,它将破坏该新创建的对象。注意,在这种情况下,*p0不是x新对象。