以下引用我的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“”使用?
答案 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
。