【发布时间】:2015-04-18 23:09:53
【问题描述】:
查看 20.8.2.2 类模板 shared_ptr [util.smartptr.shared] 我意识到 std::shared_ptr 具有模板复制构造函数和赋值运算符,允许从shared_ptr<Derived> 到 shared_ptr<Base> 当且仅当 Derived* 可转换为 Base*。这些转换(在我的理解中)仅通过模板化的复制构造函数和赋值运算符完成。但是,似乎我也可以将 shared_ptr<Derived> 传递给采用 shared_ptr<Base>& 的函数(即通过引用传递)。似乎应该有一个隐式转换运算符,但根据标准没有。
下面的代码阐明了我的意思:
#include <iostream>
#include <memory>
struct Base {};
struct Derived: Base {};
void f(const std::shared_ptr<Base>& ) {}
int main()
{
std::shared_ptr<Derived> spDerived(new Derived);
// conversion below is OK, via template copy ctor
std::shared_ptr<Base> spBase(spDerived);
// also OK, via template copy assignment operator
spBase = spDerived;
// why is this OK? Cannot see any conversion operators in
// 20.8.2.2 Class template shared_ptr [util.smartptr.shared]
f(spDerived);
}
我的问题:在这种情况下,谁在调用f(spDerived) 中执行从shared_ptr<Derived> 到shared_ptr<Base> 的转换? (对于编译器shared_ptr<Derived> 与shared_ptr<Base> 没有任何关系,即使Derived 是Base 的子级)
【问题讨论】:
-
一个临时的
std::shared_ptr<Base>是通过转换构造函数创建的,并绑定到引用。也就是说,调用相当于f(std::shared_ptr<Base>(spDerived)) -
我说的是转换构造函数,而不是复制构造函数(构造函数模板永远不是复制构造函数;/end pedantic 模式)。无论如何,你怎么知道没有构造函数被调用?由于您的函数是无操作的,很可能整个调用都被优化掉了。
-
@IgorTandetnik 我想我明白发生了什么,编译器可以执行一次用户定义的转换,并且可以调用模板转换 ctor...然后将 temp 绑定到 const ref。跨度>
-
您的问题和下面接受的答案都谈到了模板复制构造函数。正如伊戈尔已经解释的那样,没有这样的事情。构造函数模板永远不能是复制/移动构造函数。此处使用的构造函数是编号为 (9) here 的第二个构造函数。您已经了解这里发生了什么,但是删除
f的参数类型中的const并查看代码如何编译失败(在MSVC 上不会失败)可能会很有趣。
标签: c++ c++11 type-conversion shared-ptr implicit-conversion