C++ 为什么我的共享\u ptr能够从原始指针隐式构造?
我正在我的应用程序中的C++ 为什么我的共享\u ptr能够从原始指针隐式构造?,c++,shared-ptr,C++,Shared Ptr,我正在我的应用程序中的std::shared_ptr下放置一个类,转换现有代码。我的理解是,来自原始指针的shared\u ptr构造函数是显式的(例如),这对我来说非常有意义。然而,我在我的应用程序中看到了一件奇怪的事情,在我看来,构造函数似乎是隐式的。我不明白这怎么可能 首先,我有一个typedef用于我的shared\u ptr类型: typedef std::shared_ptr EidosPropertySignature_CSP 然后我有一些代码,在其中我构造了一个新对象,并将其添加
std::shared_ptr
下放置一个类,转换现有代码。我的理解是,来自原始指针的shared\u ptr
构造函数是显式的(例如),这对我来说非常有意义。然而,我在我的应用程序中看到了一件奇怪的事情,在我看来,构造函数似乎是隐式的。我不明白这怎么可能
首先,我有一个typedef
用于我的shared\u ptr
类型:
typedef std::shared_ptr EidosPropertySignature_CSP代码>
然后我有一些代码,在其中我构造了一个新对象,并将其添加到共享指针的向量中:
std::vector<EidosPropertySignature_CSP> properties;
properties.emplace_back(new EidosPropertySignature(...constructor parameters...));
std::向量属性;
重新放置(新的EidosPropertySignature(…构造函数参数…);
这种编译甚至没有任何警告。我不知道如何–新的EidosPropertySignature的结果是一个EidosPropertySignature*
,它不应该隐式转换为向量所持有的EidosPropertySignature\u CSP
,对吗?我非常希望这个构造产生编译错误,正如我所认为的那样。为什么不呢?我有没有办法修改我的方法使之生效?这里没有隐式转换emplace_back
将其参数直接转发给元素类型的构造函数以构造新元素:
追加一个类型为T
的对象,该对象由std构造::前进(参数)..
因此,emplace\u back
本质上是一个直接的构造函数调用<另一方面,代码>推回将不起作用,因为这实际上需要转换
在纯粹的概念层面上,隐式转换是指允许在必要时将某种类型的值转换为另一种类型的值,这可能是较长转换序列的一部分。转换是关于建造桥梁。通过隐式转换,您可以告诉编译器:这里有一个从a
到B
的桥梁,您可以使用它四处走动。通过显式转换,您可以说:这是从a
到B
的桥梁,只有在我明确告诉您转到B
时才使用它;特别是,如果你只是想通过B
去别的地方,不要使用它。当你写emplace\u back
时,你明确地说“构造一个元素”emplace_back
明确表示要创建元素类型的对象。您明确告诉编译器转到B
。如果您查看以下内容,则安置回
…没有任何隐含的含义:
元素是通过std::allocator\u traits::construct
构造的,它通常使用placement new在容器提供的位置就地构造元素。参数args。。。作为std::forward(args)…
转发给构造函数
发动机罩下发生的基本情况是:
new (storage) EidosPropertySignature_CSP(<emplace_back args>)
新(存储)EidosPropertySignature_CSP()
调用的显式构造函数,直接从传递的参数构造元素
元素是通过std::allocator\u traits::construct
构造的,它通常使用placement new在容器提供的位置就地构造元素
请注意,将元素构造为::new(static_cast(p))T(std::forward);元素类型的构造函数是explicit
,与否无关
(强调矿山)
直接初始化比复制初始化更允许:复制初始化只考虑非显式构造函数和非显式用户定义的转换函数,而直接初始化考虑所有构造函数和所有用户定义的转换函数
另一方面,将shared\u ptr
作为参数类型,当传递原始指针时,必须隐式地将其转换为shared\u ptr
,这是格式错误的,因为显式的
转换构造函数不会被考虑在内。因为使用emplace\u back
,它不是隐式的
该函数类似于模板引用emplace\u back(Args&&…Args)
,因此在本例中,您有一个参数,eidoPropertySignature*
,因此没有问题
然后将使用std::forward(args)…
调用std::shared\u ptr
构造函数,该构造函数可以调用显式构造函数
template<class T, class... Args> T construct(Args...args)
{
return T(std::forward<Args>(args)...);
}
int main()
{
int *x = new int();
std::shared_ptr<int> a = x; // error
std::shared_ptr<int> b(std::forward<int*>(x)); // OK
std::shared_ptr<int> c = construct<std::shared_ptr<int>>(x); // OK
}
模板T构造(Args…Args)
{
返回T(标准:正向(参数)…);
}
int main()
{
int*x=新的int();
std::shared_ptr a=x;//错误
std::shared_ptr b(std::forward(x));//确定
std::shared_ptr c=construct(x);//确定
}
正如您自己所说,shared\u ptr有一个接受原始指针的显式构造函数。该构造函数被调用。您为什么希望它不起作用?我不调用显式构造函数。我只是将一个eidoPropertySignature*
传递给emplace\u back()
。因此,转换是隐式完成的。或者我不明白构造函数声明为显式
?这意味着什么?但我确实认为我理解了这一点!:-O我希望必须执行类似emplace\u back(eidoPropertySignature\u CSP(new…)
或emplace\u back(shared\u ptr(new…)
。这不是构造函数的全部要点是明确的吗?@bhalleremplace\u back
vspush\u back
的全部要点是emplace\u back
接受元素类型的构造函数的参数,而不是元素类型的直接实例。从Michael Kenzel下面的回答中,我现在明白了。我将请在下面进一步说明他的答案