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

Sil*_*nic 2 c++ copy-constructor implicit-conversion copy-initialization copy-elision

以下来自我的C++书籍的引文:

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

对我来说,这个粗体位会产生一些模糊性.它使得听起来像右手操作数被转换为类类型,然后使用复制构造函数,例如;

string s = "hello";
Run Code Online (Sandbox Code Playgroud)

会成为...

string s = string("hello"); 
Run Code Online (Sandbox Code Playgroud)

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

#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";
}
Run Code Online (Sandbox Code Playgroud)

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

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

string null_book = "9-999-99999-9"; 
Run Code Online (Sandbox Code Playgroud)

string null_book("9-999-99999-9");
Run Code Online (Sandbox Code Playgroud)

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

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

 string null_book = "9-999-99999-9"
Run Code Online (Sandbox Code Playgroud)

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

M.M*_*M.M 6

string null_book = "9-999-99999-9";手段string null_book = string("9-999-99999-9");.

这使用了const char *构造来构造一个临时对象,然后null_book构成复制/移动从暂时对象,然后临时对象被销毁.

(复制/移动构造意味着如果可用则使用移动构造函数;否则使用复制构造函数).

但是,此方案也适用于复制省略.你实际上在你的问题中引用了复制省略规范,所以我不再重复了.

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

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

有些编译器允许通过开关禁用复制省略,例如gcc/clang -fno-elide-constructors.

有关copy elision的更多信息