2015-04-18 31 views
0

看着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>&(即通过引用传递)的函数。似乎应该有一个隐式转换运算符,但根据标准,没有。当通过引用传递时,std :: shared_ptr如何通过类层次转换?

下面的代码阐明了我的意思:

#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); 
} 

我的问题:在这种情况下,谁是执行从shared_ptr<Derived>转换为shared_ptr<Base>呼叫f(spDerived)? (为shared_ptr<Derived>shared_ptr<Base>没有任何关系,即使DerivedBase子编译)

+3

通过转换构造函数创建临时'std :: shared_ptr ',并绑定到引用。换句话说,调用等价于'f(std :: shared_ptr (spDerived))' –

+2

我说转换构造函数,而不是复制构造函数(构造函数模板从不复制构造函数; /结束迂腐模式)。无论如何,你怎么知道没有构造函数被调用?由于你的功能是无操作的,很可能整个呼叫都被优化掉了。 –

+0

@IgorTandetnik我想我明白发生了什么,编译器可以执行一个用户定义的转换,并且可以调用模板转换ctor ... temp然后绑定到const ref。 – vsoftco

回答

2

临时通过模板拷贝构造函数创建和副本是什么被引用。 ctor是隐含的,所以在这种情况下可以合法地调用它。从根本上说,这个电话与f(std::string); f("hello");之间没有什么区别。同样的机制正在发挥作用。这是一个常规的隐式转换。

+0

虽然我通过const引用,所以它应该是安全的。我只是不明白为什么复制构造函数被调用。 – vsoftco

+0

@vsoftco:哦,我必须完全脑筋急转弯,根本没有看到'const'。复制构造函数因为是隐式的而被调用,所以编译器可以隐式创建一个临时的。 – Puppy

+0

事实上,我意识到这只是一个用户定义的转换,因此编译器会继续并执行它,这会使调用有效。现在很清楚,我不知道为什么我以前见过它。 – vsoftco