下面的代码给出了预期的分段错误。
struct B{
shared_ptr<B> createShared(){ return shared_ptr<B>(this);}
};
int main()
{
shared_ptr<B> p1 = make_shared<B>();
shared_ptr<B> p2 = p1->createShared();
return 0;
}
但是当我更改代码时
shared_ptr<B> p1 = make_shared<B>();
to
shared_ptr<B> p1(new B);
程序编译并运行而不会发生任何崩溃。
有人可以解释一下导致这两种情况之间行为改变的确切原因。
注意: - 我知道这不是从这个指针创建共享指针的正确方法,我正在寻找的是这两种情况之间行为改变的原因。我使用的编译器是clang ++ - 3.8和g ++ - 5.4。
答案 0 :(得分:0)
在没有崩溃的情况下运行并不意味着您的程序是正确的。当您点击未定义的行为时,结果是未定义的。程序的两个版本都会销毁同一个对象两次,因为您基本上是从同一个原始指针创建两个单独的shared_ptrs。因此,其中一个尝试删除导致未定义行为的无效指针。
创建shared_ptr的两种方法实际上存在差异。让我们考虑shared_ptr<B> p1(new B);
,首先分配一个B,然后将raw_ptr初始化为原始ptr为B.在shared_ptr初始化期间,分配一个包含使用计数和同步对象的控制块。这是两个单独的分配。然而,make_shared
分配一个足够大的块来保存控制块和实际对象,因此生成的内存布局稍有不同,清理代码也会略有不同。
正如一些程序员提到的那样,你应该使用std::enable_shared_from_this。