2016-10-10 33 views
4

我试图定义一个std::shared_ptrnew运营商通过以下方式时:错误定义的std :: shared_ptr的新运营商

#include <memory> 

struct A { 
}; 

int main() { 

    std::shared_ptr<A> ptr = new A(); 

    return 0; 
} 

,但我获得以下编译时错误:

main.cpp: In function 'int main()':

main.cpp:8:30: error: conversion from 'A*' to non-scalar type 'std::shared_ptr' requested std::shared_ptr ptr = new A();

不管怎样,下面肯定能行:

 std::shared_ptr<A> ptr{new A()}; 

是否有人对你ķ现在为什么会发生?

回答

6

tl; dr:这是相关构造函数为explicit的结果。

当您使用=进行初始化时,您将调用复制初始化。 C++不允许从原始指针中复制初始化shared_ptr,因为它最终会因为从一些任意的原始指针意外转换到实际上不管理它的shared_ptr而过于容易。

这样,您可以将原始指针“套入”shared_ptr的唯一方法是非常有意和非常明确的(正如您在第二个示例中正确完成的那样)。现在,只有在这个初始化程序中,您必须记住不要使用您已经在别处管理的指针。

对于特定行std::shared_ptr<A> ptr = new A()有什么实际危险吗?但是,你所看到的是各种C++规则协同工作的结果。

3

你可以想象你的陈述也是这样的2班轮。

A* a = new A(); 
std::shared_ptr<A> ptr = a; 

而在这种情况下,这可能是更复杂的代码,它可能会导致潜在的缺陷,从而正确初始化复制不允许原始指针。

想象

A* a = new A(); 
//..... 
std::shared_ptr<A> ptr = a; 
//..... 
std::shared_ptr<A> ptr2 = a; //second ptr holding a... UB 

在这里,你将有2个共享的支持导致麻烦同一对象的指针。

为了避免这些“隐式”错误,C++不允许这种初始化。

虽然你仍然可以与构造函数相同,但它更“冗长”,而且更难以意外地分配指针。

std::shared_ptr<A> ptr{ new A() }; 

这看起来更像是构建一个新的对象,并且可能不会导致意外错误分配。

另外,优选方式来创建在现代共享指针是

auto ptr = std::make_shared<A>(); 
+3

否,即不分配。 –

+0

@LightnessRacesinOrbit是的,你是对的。我重述了这一部分。 – Hayt