复制构造函数被多次调用c ++
Posted
技术标签:
【中文标题】复制构造函数被多次调用c ++【英文标题】:copy constructor being called multiple times c++ 【发布时间】:2015-08-23 15:00:29 【问题描述】:我正在阅读 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!
我不明白输出。对我来说,它表明为 line1 调用了普通构造函数,然后为 line2 调用了一个复制构造函数,然后为 2 个对象调用了 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 次“释放内存”,中间也有 1 次,我真的很困惑,你能帮帮我吗?
谢谢
【问题讨论】:
【参考方案1】:这是简单构造的:
Line line1(10);
正如你所知道的,这是你的复制构造函数被调用的地方:
Line line2 = line1;
到目前为止一切顺利。现在看看display
的签名:
void display(Line obj);
这就是我们所说的按值传递。 Pass-by-value 是一种参数形式,它导致从传入的对象构造一个新对象。因此,这里的两个调用:
display(line1);
display(line2);
都在调用复制构造函数以将line1
和line2
放入函数局部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
现在是它自己的对象,独立于line1
或line2
的生命周期,当obj
超出范围时,就像它在函数末尾所做的那样,它的析构函数被调用。这可以解释对析构函数的总共四个调用:一个用于原始简单构造的对象 (line1
),一个用于复制构造的对象 (line2
),两个用于两个函数本地 obj
s。
如果您想避免像您在问题中指出的那样复制,请使用pass-by-reference。
【讨论】:
【参考方案2】:void display(Line obj)
为其参数调用复制构造函数,
您可以使用 const 引用来避免复制 (void display(const Line& obj)
)。
【讨论】:
【参考方案3】:示例如下:
线 line1(10); // 普通构造函数分配ptr
线 line2 = line1; // 复制构造函数分配ptr
显示(第 1 行); /* 复制构造函数分配ptr,因为函数是这样的:
void display(Line obj);
这将使对象的副本进入方法,就像它是一个 int 一样,例如。如果要消除此副本,请更改为
void display(const Line& obj);
传递一个引用。 */
/* 接下来调用函数并打印
行长:10
然后副本的析构函数在函数的末尾被调用,在它返回之前。
释放内存!
*/
display(line2);/* 接下来在第二个函数调用中重复相同的模式:
复制构造函数分配ptr。
行长:10
释放内存! */
返回 0; /* 最后,line1 和 line2 都被销毁:
释放内存!
释放内存!
*/
【讨论】:
【参考方案4】:q.1> 为什么最初多次调用复制构造函数
您致电display(line)
、display(line2)
。 void display(Line obj)
被定义为作为参数接收 Line
对象,因此每次调用 display
时,都会为该函数复制该对象(就像您向函数发送整数一样,它的值将被复制,以便如果函数修改了该整数,除了函数的范围外,它不会影响任何东西)。为了减少复制构造函数的数量,您可以将display
定义为void display(Line& obj)
。但请注意,对obj
所做的每一次修改都会反映在main()
中。
q.2>4 次“释放内存”,这也是介于两者之间的,我真的 困惑,你能帮帮我吗?
两倍于您的预期(一个用于line
,另一个用于line2
),另外两次用于复制到display
函数的对象。一旦display
的流程被执行,它会破坏所有的本地对象,函数参数被认为是一个本地对象。
【讨论】:
以上是关于复制构造函数被多次调用c ++的主要内容,如果未能解决你的问题,请参考以下文章