为什么会调用用于初始化另一个对象的对象的复制构造函数?

Why does the copy constructor of an object that is being used for intializing another object gets invoked?

提问人:nyms1 提问时间:10/13/2022 最后编辑:Vlad from Moscownyms1 更新时间:10/13/2022 访问量:60

问:

class point
{
public:
    point(double x, double y) : x(x), y(y)
    {
        std::cout << "point parameterized constructor of: "
        << getThis() << std::endl;
    }

    point(const point& that) : x(that.x), y(that.y)
    {
        std::cout << "point copy constructor of: "
        << getThis() << std::endl;
    }

    ~point()
    {
        std::cout << "point destructor of: "
        << getThis() << std::endl;
    }
private:
    double x;
    double y;
    point* getThis() { return this; }
};

class line
{
public:
    line(const point& startPoint, const point& endPoint) :
    startPoint(startPoint)
    endPoint(endPoint)
    {
        std::cout << "line parameterized constructor: " << getThis() << std::endl;
    }
    ~line()
    {
        std::cout << "line destructor of: "
        << getThis() << std::endl;
    }
private:
    point startPoint;
    point endPoint;
    line* getThis() { return this; }
};

int main()
{
    point p1(3.0, 4.0);
    point p2(5.0, 6.0);

    line l1(p1, p2);

    return 0;
}

程序输出:

point parameterized constructor of: 0x577fffc00
point parameterized constructor of: 0x577fffbe0
point copy constructor of: 0x577fffbb0
point copy constructor of: 0x577fffbc8
lineSegment parameterized constructor of: 0x577fffbb0
lineSegment destructor of: 0x577fffbb0
point destructor of: 0x577fffbc8
point destructor of: 0x577fffbb0
point destructor of: 0x577fffbe0
point destructor of: 0x577fffc00

我不明白 point 的复制构造函数是如何被调用 2 次的(每个点参数 1 次)的原因最初是,行构造函数参数不是常量引用。编译器对行构造函数发出了此警告

Clang-Tidy: The parameter 'endPoint' is copied for each invocation but only used as a const reference; consider making it a const reference
line(point startPoint, point endPoint) : startPoint(startPoint), endPoint(endPoint) {...}

这是输出:

point parameterized constructor: 0x8feedffa40
point parameterized constructor: 0x8feedffa20
point copy constructor: 0x8feedffa60
point copy constructor: 0x8feedffa80
point copy constructor: 0x8feedff9f0
point copy constructor: 0x8feedffa08
lineSegment parameterized constructor: 0x8feedff9f0
point destructor: 0x8feedffa80
point destructor: 0x8feedffa60
lineSegment destructor: 0x8feedff9f0
point destructor: 0x8feedffa08
point destructor: 0x8feedff9f0
point destructor: 0x8feedffa20
point destructor: 0x8feedffa40

正如你所看到的,该点的复制构造函数被调用了 4 次(每个点参数 2 次)。我假设当我进行参数 const point 引用时,所有 4 次调用都会消失。相反,他们减半了。为什么?

C++ C++14 复制构造函数

评论

6赞 M.M 10/13/2022
在第一个代码中,通过复制参数来初始化成员startPoint(startPoint)startPointstartPoint

答:

2赞 Vlad from Moscow 10/13/2022 #1

在类的这个构造函数中line

line(const point& startPoint, const point& endPoint) :
startPoint(startPoint)
endPoint(endPoint)
{
    std::cout << "line parameterized constructor: " << getThis() << std::endl;
}

对于数据成员使用了 Copy 构造函数,并且在此 mem-initializer 列表中pointstartPointendPoint

startPoint(startPoint)
endPoint(endPoint)

在此构造函数中

line(point startPoint, point endPoint) : startPoint(startPoint), endPoint(endPoint) {...}

如果引用不接受参数,则会多次调用复制构造函数来初始化参数。