复制构造函数被多次调用c ++

copy constructor being called multiple times c++

我正在阅读 tutorialspoint.com http://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm

提供的 c++ 复制构造函数教程

在他们的示例代码之一中:

#include <iostream>

using namespace std;

class Line
{
public:
    int getLength(void);
    Line(int len);          // simple constructor
    Line(const Line &obj);  // copy constructor
    ~Line();                // destructor

private:
    int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
    *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}

int Line::getLength(void)
{
    return *ptr;
}

void display(Line obj)
{
    cout << "Length of line : " << obj.getLength() << endl;
}

// Main function for the program
int main()
{
    Line line1(10);

    Line line2 = line1; // This also calls copy constructor

    display(line1);
    display(line2);

    return 0;
}

输出为

Normal constructor allocating ptr
Copy constructor allocating ptr.
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Freeing memory!

我不明白输出。对我来说,这表明第 1 行调用了普通构造函数,然后第 2 行调用了一个复制构造函数,然后 2*"freeing memory" 为 2 个对象

我认为的输出是:

Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Length of line : 10
Freeing memory!
Freeing memory!

q.1> 为什么最初会多次调用复制构造函数

q.2>4 次 "freeing memory" 中间还有一次,我真的很困惑,你能帮帮我吗?

谢谢

void display(Line obj) 为其参数调用复制构造函数,
您可以使用 const 引用来避免复制 (void display(const Line& obj)).

这是简单构造的:

Line line1(10);

如您所知,这是调用复制构造函数的地方:

Line line2 = line1;

到目前为止一切顺利。现在看看 display:

的签名
void display(Line obj);

这就是我们所说的按值传递。传值是一种参数形式,它使传入的对象构造一个新对象。因此,这里的两个调用:

display(line1);
display(line2);

都在调用复制构造函数以将 line1line2 放入函数局部 obj 变量中。

这大致相当于:

// Instead of calling display, this happens instead:
{ // Entering a new scope
    Line obj = line1;
    cout << "Length of line : " << obj.getLength() << endl;
} // Exiting scope

{ // Entering a new scope
    Line obj = line2;
    cout << "Length of line : " << obj.getLength() << endl;
} // Exiting scope

obj 现在是它自己的对象,独立于 line1line2 的生命周期,当 obj 超出范围时,就像它在函数结束时,它的析构函数被调用。这将解释对析构函数的四次调用:一次用于原始简单构造的对象 (line1),一次用于复制构造的对象 (line2),两次用于两个函数局部 objs.

如果您想避免像您在问题中指出的那样复制,请使用 pass-by-reference

例子是这样的:

第1行(10); // 普通构造函数分配 ptr

第2行=第1行; // 复制构造函数分配 ptr

显示(第1行); /* 复制构造函数分配 ptr,因为函数是这样的:

无效显示(行对象);

例如,这将复制进入方法的对象,就好像它是一个 int 一样。如果要消除这个副本,改为

无效显示(const Line& obj);

其中传递了一个引用。 */

/* 接下来调用函数并打印

行的长度:10

然后在函数末尾调用副本的析构函数,在它之前 returns.

正在释放内存!

*/

display(line2);/* 接下来用第二个函数调用重复相同的模式:

复制构造函数分配指针。

行的长度:10

正在释放内存! */

return 0; /* 最后,line1 和 line2 都被销毁:

正在释放内存!

正在释放内存!

*/

q.1> why copy constructor is called multiple times initially

您呼叫display(line)display(line2)void display(Line obj) 被定义为作为参数接收 Line 对象,因此每次调用 display 时,都会为该函数复制该对象(就像您向函数发送整数一样,它value 将被复制,这样如果函数修改了那个整数,它不会影响任何东西,除了函数的范围)。为了减少复制构造函数的数量,你可以将display定义为void display(Line& obj)。但是请注意,对 obj 所做的每个修改都会反映在 main().

q.2>4 times "freeing memory" and that too one in between, I am really confused, could you help me out.

如您所料两次(一次用于 line,另一次用于 line2),另外两次用于复制到 display 函数的对象。一旦display的流程执行,它会破坏所有的本地对象,函数参数被认为是一个本地对象。