使用复制构造函数进行隐式类类型转换

Do implicit class-type conversions use the copy-constructor?

本文关键字:类型转换 复制 构造函数      更新时间:2023-10-16

以下引用自我的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";
}

应该产生"The second way, The second way, The first way"。然而,它却打印出"The second way, The second way"。从这里我可以得出结论,它使用的是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 &"构造函数设置为私有(其余部分设置为公共),那么我的程序将无法运行。为什么必须为甚至不涉及复制构造函数的隐式转换定义复制构造函数?"string null_book = "9-999-99999-9"使用什么构造函数?

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

关于复制省略的更多信息