c++ - 确定在 C++ 代码中调用了哪些复制构造函数

标签 c++ class oop constructor operator-overloading

我用 1 个非参数构造函数、1 个参数构造函数、2 个复制构造函数、1 个赋值运算符和 1 个加号运算符编写了一个简单的 C++ 类示例。

class Complex {
protected:
    float real, img;
public:
    Complex () : real(0), img(0) {
        cout << "Default constructor\n";
    }

    Complex (float a, float b) {
        cout << "Param constructor" << a << " " << b << endl;
        real = a;
        img = b;
    }

    // 2 copy constructors
    Complex( const Complex& other ) {
        cout << "1st copy constructor " << other.real << " " << other.img << endl;
        real = other.real;
        img = other.img;
    }

    Complex( Complex& other ) {
        cout << "2nd copy constructor " << other.real << " " << other.img << endl;
        real = other.real;
        img = other.img;
    }

    // assignment overloading operator
    void operator= (const Complex& other) {
        cout << "assignment operator " << other.real << " " << other.img << endl;
        real = other.real;
        img = other.img;
    }

    // plus overloading operator
    Complex operator+ (const Complex& other) {
        cout << "plus operator " << other.real << " " << other.img << endl;
        float a = real + other.real;
        float b = img + other.img;
        return Complex(a, b);
    }

    float getReal () {
        return real;
    }

    float getImg () {
        return img;
    }
};

我在 main 中完全像这样使用这个类:

int main() {
    Complex a(1,5);
    Complex b(5,7);
    Complex c = a+b; // Statement 1
    system("pause");
    return 0;
}

结果打印为:

Param constructor 1 5
Param constructor 5 7
plus operator 5 7
Param constructor 6 12

我认为语句 1 中必须使用复制构造函数,但我真的不知道调用的是哪一个。 请告诉我是哪一个,为什么? 非常感谢

最佳答案

编译器省略了对复制构造函数的调用(实际上,两次 调用)。根据 C++11 标准的第 12.8/31 段,这是允许的(但不是强制的!),即使构造函数或析构函数有副作用:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. [..] This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

[...]

— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

如果编译器没有省略对复制构造函数的调用,那么第一个将被选择两次,即具有以下签名的那个:

Complex( const Complex& other )

原因是:

  • operator + 返回的值是从临时 (Complex(a, b)) 复制初始化的,并且只有 的左值引用const 可以绑定(bind)到临时对象。如果 operator + 是这样写的,事情就会不同:

    Complex operator+ (const Complex& other) {
        // ...
        Complex c(a, b);
        return c;
    } 
    

    在这种情况下,将调用第二个复制构造函数,因为 c 不是 const 限定的并且是左值,因此它可以绑定(bind)到左值引用到非const;

  • main() 中的对象 c 是从右值复制构造的(operator + 返回的值也是一个临时的)。无论 operator + 如何返回其 Complex 对象,只要它按值返回,都是如此。因此,只要不执行复制省略,就会选择第一个复制构造函数。

如果您正在使用 GCC 并想验证此行为,请尝试设置 -fno-elide-constructors 编译标志(Clang 也支持它,但 3.2 版有一个错误,我没有知道它是否已修复)。

关于c++ - 确定在 C++ 代码中调用了哪些复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16636236/

相关文章:

c++ - Qt5.2 QNetwork,写入了多少字节?

c++ - 如何以最优雅的C++方式设计一个已经预定义标准颜色的颜色类?

c++ - 如何从 if 语句中获取类模板的实例? (C++)

c++ - 观察者模式——竞争条件

php - undefined index 和 undefined variable ,但两者都已定义! (我认为....)

c++ - 将在抽象基类上定义的 vector 的元素与具体的派生类进行匹配

c++ - 有人可以解释这个模板函数声明语法吗

c++ - 将 std::deque 内容复制到字节数组的最有效方法

java - 当只有一个类变量的副本在该特定类的所有实例之间共享时,为什么会出现 "reinitialise the class variable"

JavaScript - 这个这个