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

strange behaviour of copy constructor between function parameter and temporary variable

本文关键字:构造函数 复制 之间 参数 变量 函数      更新时间:2023-10-16

我有例如:

#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}

正如我们所看到的,参数ptemporary variable是用复制构造函数构造的。点的成员是建筑类型,因此,如果在构造函数中未指定初始化列表,则不能默认将它们初始化。

问题:

为什么参数 p在到达Point(const Point&)构造函数中 cout之前, xy具有有效的 CC_4和 CC_5,而 temporary variable具有垃圾值?

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

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

在复制构造函数中,您未能在构造函数初始化列表中初始化数据成员。但是后来您阅读了调用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