我正在浏览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&GT;为什么复制构造函数最初被多次调用
q.2&gt; 4次“释放记忆”,而且介于两者之间,我真的很困惑,你能帮助我吗?
由于
答案 0 :(得分:3)
这是简单的构造:
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
),两个用于两个函数本地{{ 1}} S上。
如果您想避免在问题中指明的副本,请使用pass-by-reference。
答案 1 :(得分:0)
void display(Line obj)
为其参数调用复制构造函数,
您可以使用const引用来避免复制(void display(const Line& obj)
)。
答案 2 :(得分:0)
示例如下:
第1行(10); //普通构造函数分配ptr
第2行= line1; //复制构造函数分配ptr
显示器(LINE1); / *复制构造函数分配ptr,因为函数是这样的:
void display(Line obj);
这将使对象的副本进入方法,就像它是一个int一样。如果要删除此副本,请更改为
void display(const Line&amp; obj);
传递参考。 * /
/ *接下来调用函数并打印
行长:10
然后在函数结束时调用副本的析构函数,然后返回。
释放记忆!
* /
display(line2); / *接下来,使用第二个函数调用重复相同的模式:
复制构造函数分配ptr。
行长:10
释放记忆! * /
返回0; / *最后,line1和line2都被破坏了:
释放记忆!
释放记忆!
* /
答案 3 :(得分:0)
Q.1&GT;为什么复制构造函数最初被多次调用
您致电display(line)
,display(line2)
。 void display(Line obj)
被定义为接收参数Line
对象,因此每次调用display
时,都会为该函数复制该对象(就像您向函数发送整数一样,将复制值,以便如果函数修改了该整数,它将不会影响除函数范围之外的任何内容)。为了减少复制构造函数的数量,您可以将display
定义为void display(Line& obj)
。但请注意,obj
上的所有修改都会反映在main()
。
q.2&gt; 4次“释放记忆”,而且介于两者之间,我真的 很困惑,你能救我吗?
按预期的两次(一次用于line
,另一次用于line2
),另外两次用于复制到display
函数的对象。一旦执行display
流,它就会破坏所有本地对象,并且函数参数被认为是本地对象。