【发布时间】:2020-11-19 10:49:48
【问题描述】:
下面是MyStruct 类实现,它具有默认构造函数和复制构造函数。
struct MyStruct {
MyStruct(const string& name) {
cout << "Basic constructor called" << endl;
name_ = name;
}
MyStruct(const MyStruct& S) {
cout << "Copy constructor called" << endl;
name_ = S.name_;
}
string name_;
}
以下列方式创建对象:MyStruct S = MyStruct("Hello"); 使用“Hello”参数调用构造函数。我怀疑我的编译器(gcc 版本 7.5.0)通过避免创建临时对象来进行优化MyStruct("Hello") 对象。
但是,编译器并没有优化赋值运算符的类似情况:
MyStruct& operator=(const string& name) { // First assignment operator
name_ = name;
return *this;
}
MyStruct& operator=(const MyStruct& S) { // Second assignment operator
name_ = S.name_;
return *this;
}
将 S 重新分配给另一个结构:
MyStruct S = MyStruct("Hello"); // initial construction
S = MyStruct("world"); // reassignment
第二次调用构造函数来构造临时的MyStruct("world") 对象。之后,调用第二个赋值运算符。
问题:
-
有没有办法修改代码,以便调用带有参数
"world"的第一个赋值运算符? -
是现代 C++ 标准的第一个优化部分(即适用于所有编译器),还是仅适用于特定编译器?
【问题讨论】:
-
如果要调用
MyStruct& operator=(const string& name),则需要像S = "world";一样将字符串直接赋值给S -
编译器不能通过赋值来做到这一点。采用参数和赋值运算符的构造函数是用户定义的函数。而那些可以做......任何事情。编译器无法证明调用
operator=(const string&)与调用MyStruct(const string&)然后调用operator=(const MyStruct&)具有相同的行为。它不能进行改变行为的优化。 -
"现代 C++ 编译器能否优化临时变量的赋值运算符?" - 为什么不简单地使用启用优化的现代编译器编译代码并检查生成的程序集?这将明确回答您的问题。
-
@mercury - 这在 C++ 的早期是不可能的。但是...对于构造函数,您没有 existing 对象被修改(可能具有不变量)。它只是需要初始化的存储。在这种情况下,可观察行为的变化被认为更合理,因此被标准允许。
标签: c++ c++11 constructor copy-constructor forwarding