【发布时间】:2019-01-10 00:26:55
【问题描述】:
假设我们有一个自定义字符串类,如下所示
using namespace std;
class CustomStr {
public:
const char* s;
// converting constructor
CustomStr(const char* s) : s (s) {
cout << "Constructor called" << endl;
}
// Copy constructor
CustomStr(const CustomStr& cs) : s (cs.s) {
cout << "Copy Constructor called" << endl;
}
};
让我们考虑以下代码:
int main() {
CustomStr cs("Some char pointer");
CustomStr cs_copy = cs;
return 0;
}
在上面的例子中,对于CustomStr cs_copy = cs,我们希望先调用转换构造函数,然后调用复制构造函数,我们得到了预期的相应输出
$ ./a.out
Constructor called
Copy Constructor called
现在,考虑下面的代码
int main() {
CustomStr cs_copy = CustomStr("Some char pointer");
return 0;
}
在这种情况下,我也认为应该进行 2 个构造函数调用 - 为 CustomStr("Some char pointer") 转换构造函数调用,为 CustomStr cs_copy = CustomStr("Some char pointer") 调用复制构造函数。但是,输出显示只调用了转换构造函数。
我无法解释这是怎么发生的。我希望它对于编译器进行优化来说是一个容易实现的成果 - 但我想了解这种优化在什么情况下起作用。
【问题讨论】:
-
是的,这是编译器优化。在最近的 C++ 修订版中,何时允许这种优化和其他类型的优化的规则已经改变了——有时是相当大的。在某些情况下,允许编译器优化复制构造或复制分配,即使它有副作用。在某些情况下,它甚至是必需的。不必担心这一点——遵守规则。不要在特定情况下对复制构造函数或发生的复制赋值引入脆弱的依赖,让编译器担心生成正确的代码。
-
注意“默认构造函数”是一个技术术语,它不描述您的第一个构造函数。通常意义上的“默认构造函数”是可以与零参数一起使用的构造函数。所以
CustomStr();或CustomStr(const char* s = nullptr);都是默认构造函数。 -
@aschepler - 感谢您指出这一点。我已经相应地编辑了问题
标签: c++ class constructor copy-constructor