不调用复制构造函数

时间:2014-06-09 10:33:45

标签: c++ copy-constructor compiler-optimization

为什么在此示例程序中未调用复制构造函数?

当函数input()返回一个对象时,会生成该对象的副本,但我看不到根据控制台中的输出调用了复制构造函数。

输出:

 Enter a string: ssssssssss
 ssssssssss
 Freeing s

代码:

#include <iostream>
using namespace std;

class Sample {
    char *s;
public:
    Sample() { s = 0; }
    Sample(const Sample &sample) { cout << "copyconstructor\n"; }
    ~Sample() { if(s) delete[] s; cout << "Freeing s\n"; }

    void show() { cout << s << "\n"; }

    void set(char *str) {
        s = new char[strlen(str) + 1];
        strcpy(s, str);
    }
};

Sample input() {
    char instr[80];
    Sample str;
    cout << "Enter a string: ";
    cin >> instr;
    str.set(instr);
    return str;
}

int main() {
    Sample ob = input();
    ob.show();
    return 0;
}

1 个答案:

答案 0 :(得分:2)

由于编译器已执行优化,因此未调用复制构造函数。

优化称为RVO(或NRVO),并允许编译器在某些情况下直接在调用点处构建返回值。

大多数编译器允许您使用选项启用优化。 Clang和gcc允许你使用:

来转换elision
  

-fno-elide-constructors

此外,您的代码还有未定义的行为,因为复制构造函数不会初始化 s。在复制构造对象上调用Sample::show或析构函数将导致UB访问或删除未初始化的数据未定义。

此外,班级Sample展示UB,因为它不遵循三法则What is The Rule of Three?)。使用隐式声明的复制赋值运算符将执行s的浅表副本,这可能导致数据在销毁时被多次删除,即UB。