函数参数和临时变量之间复制构造函数的奇怪行为

时间:2017-04-18 11:50:15

标签: c++

我的例子如下:

\r\n

输出是:

#include <iostream>

using namespace std;

class Point {
private:
    int x;
    int y;

public:
    Point(int i, int j) : x{ i }, y{ j } {
        cout << "CTOR POINT: {x=" << x << ", y=" << y << ", addr=" << this << "}" << endl;
    }

    Point(const Point& p) {
        cout << "COPY CTOR from POINT: {x=" << p.x << ", y=" << p.y << ", addr=" << &p << "} to POINT: {x=" << x << ", y=" << y << ", addr=" << this << "}" << endl;
        x = p.x;
        y = p.y;
    }

    Point& operator=(const Point& p) {
        cout << "OP= from POINT: {x=" << p.x << ", y=" << p.y << ", addr=" << &p << "} to POINT: {x=" << x << ", y=" << y << ", addr=" << this << "}" << endl;
        x = p.x;
        y = p.y;
        return *this;
    }

    ~Point() {
        cout << "DTOR POINT: {x=" << x << ", y=" << y << ", addr=" << this << "}" << endl;
    }
};

Point func1(Point p) {
    cout << "entered in func1 function" << endl;
    cout << "exiting in func1 function" << endl;
    return p;               // p will be copied to temporary variable with Point(const Point&) ctor.
                            // p will be dtored.
}

int main() {
    cout << "entered in main function" << endl;
    Point p1{ 5, 10 };      // initialized p1 with Point(int, int) ctor.
    p1 = func1(p1);         // in call to func1(), p1 arg will be copied to parameter p with Point(const Point&) ctor.
                            // on return, temporary variable will be assigned to p1 using operator=(const Point&) func.
                            // temporary variable will be dtored.
    Point p2{ 500, 1000 };  // initialized p2 with Point(int, int) ctor.
    p1 = p2;                // p2 will be assigned to p1 using operator=(const Point&) func.
    cout << "exiting in main function" << endl;
                            // p2 will be dtored.
                            // p1 will be dtored.
}

我们可以看到,参数entered in main function CTOR POINT: {x=5, y=10, addr=003EFE38} COPY CTOR from POINT: {x=5, y=10, addr=003EFE38} to POINT: {x=5, y=10, addr=003EFD28} entered in func1 function exiting in func1 function COPY CTOR from POINT: {x=5, y=10, addr=003EFD28} to POINT: {x=-858993460, y=-858993460, addr=003EFD4C} DTOR POINT: {x=5, y=10, addr=003EFD28} OP= from POINT: {x=5, y=10, addr=003EFD4C} to POINT: {x=5, y=10, addr=003EFE38} DTOR POINT: {x=5, y=10, addr=003EFD4C} CTOR POINT: {x=500, y=1000, addr=003EFE28} OP= from POINT: {x=500, y=1000, addr=003EFE28} to POINT: {x=5, y=10, addr=003EFE38} exiting in main function DTOR POINT: {x=500, y=1000, addr=003EFE28} DTOR POINT: {x=500, y=1000, addr=003EFE38} p是使用复制构造函数构造的。 Point的成员是内置类型,因此,如果构造函数中未指定初始化列表,则默认情况下不能初始化它们。

问题:

为什么参数temporary variablepx之前有y510cout构造函数,而Point(const Point&)有垃圾值吗?

1 个答案:

答案 0 :(得分:0)

您的副本构造函数未正确实现。每个构造函数(包括复制构造函数)都可以有成员初始化列表。如果提供,它们将按照在类中声明数据成员的顺序执行。如果未提供,则数据成员将默认初始化。

请记住,数据成员的初始化始终在构造函数体运行之前发生。

在复制构造函数中,您无法在构造函数初始化列表中初始化数据成员。但是你后来读了它们调用了UB。你可能想这样做:

Point(const Point& p) : x{ p.x }, y{ p.y } {
    std::cout << "COPY CTOR from POINT: {x=" << p.x << ", y=" << p.y
              << ", addr=" << &p << "} to POINT: {x=" << x 
              << ", y=" << y << ", addr=" << this << "}" << endl;
}

如上所述,你不应该有UB。

Demo