隐式类类型转换是使用复制构造函数吗?

时间:2015-08-25 23:03:53

标签: c++ copy-constructor implicit-conversion copy-elision copy-initialization

以下引用我的C ++书:

  

当我们使用直接初始化时,我们要求编译器使用普通函数匹配来选择与参数最匹配的构造函数   我们提供。当我们使用复制初始化时,我们要求编译器进行复制   右侧操作数进入正在创建的对象,转换该操作数if   必要的。

对我来说,这个粗体位会产生一些含糊之处。它使声音听起来像右手操作数转换为类类型,然后使用复制构造函数,例如;

string s = "hello";

会变成......

string s = string("hello"); 

使用复制构造函数。如果这是真的那么我的测试程序;

#include <iostream>
using namespace std;

class A{
public:
    A(const A& b): data(b.data) { cout << "The first way" << endl;}
    A(const char* c): data(c) { cout << "The second way" << endl;}
    string data;

};
int main(){
    A first("hello");
    A second = "sup";
}

应该产生“第二种方式,第二种方式,第一种方式”。然而它反而打印出“第二种方式,第二种方式”。从这里我可以得出结论它是使用const char *构造函数而不是复制构造函数。我会好的,除非后来说......

  

在复制初始化期间,允许编译器(但没有义务)跳过复制/移动构造函数并直接创建对象。也就是说,允许编译器重写

string null_book = "9-999-99999-9"; 
     

进入

string null_book("9-999-99999-9");
     

但是,即使编译器省略了对复制/移动构造函数的调用,也是如此   复制/移动构造函数必须存在,并且必须在程序中的那一点可访问(例如,非私有)。

我不确定为什么复制构造函数甚至需要在这些示例中提及,不是

 string null_book = "9-999-99999-9"

总是隐含地意味着仍然使用const char *构造函数?实际上,我不需要定义复制构造函数以使上述工作正常。但是,如果我把“const A&amp;”放进去构造函数作为私有(其余公共)然后我的程序将无法运行。为什么必须为不涉及它的隐式转换定义复制构造函数?什么构造函数“string null_book =”9-999-99999-9“”使用?

1 个答案:

答案 0 :(得分:5)

string null_book = "9-999-99999-9";表示string null_book = string("9-999-99999-9");

这使用const char *构造函数构造临时对象,然后null_book 从临时对象复制/移动构造,然后销毁临时对象。

复制/移动构造表示如果可用则使用移动构造函数;否则使用复制构造函数。)

但是,此方案也符合 copy elision 的条件。你实际上在你的问题中引用了复制省略规范,所以我不会重复它。

编译器可以选择为null_book和临时对象使用相同的内存空间,并省略对临时对象析构函数和null_book复制/移动构造函数的调用。

在您的情况下,编译器确实选择这样做,这就是您没有看到任何复制构造函数输出的原因。

某些编译器允许通过交换机禁用复制省略,例如gcc / clang -fno-elide-constructors

More info about copy elision