提问人:Jony 提问时间:4/22/2010 最后编辑:pkthapaJony 更新时间:4/24/2023 访问量:88659
为什么复制构造函数应该在 C++ 中通过引用接受其参数?
Why should the copy constructor accept its parameter by reference in C++?
答:
因为如果它不是通过引用,它就是通过值。为此,请创建一个副本,为此,请调用 copy 构造函数。但要做到这一点,我们需要创建一个新值,所以我们调用复制构造函数,依此类推......
(你会有无限递归,因为“要制作副本,你需要制作副本”。
评论
object o(other_object)
object
object
object
object o(&other_object)
因为按值传递会调用复制构造函数:)
如果你按值传入它,它将是无限递归的
按引用传递的替代方法是按值传递。按值传递实际上是按副本传递。需要复制构造函数来制作副本。
如果必须创建一个副本来调用复制构造函数,那将是一个难题。
(我认为无限递归会发生在编译器中,你永远不会真正得到这样的程序。
除了合理原因外,§12.8/3 中的标准也禁止这样做:
构造函数的声明 类 X 的格式不正确,如果它的第一个 参数的类型(可选 cv- 合格)X,要么没有 其他参数或其他所有其他参数 parameters 具有默认参数。
评论
每当您调用函数时(例如:int f(car c))
它采用内置数据类型以外的参数(此处为 car)
复制调用方提供的实际对象的要求
添加到被调用函数参数中的变量。
例:
car carobj;
f(carobj);
也就是说,复制到 .carobj
c
carobj
需要复制到函数中的参数。c
f
为了实现复制,调用了复制构造函数。
在这种情况下,使用传递值调用的函数,或者换句话说,函数被声明为接受传递值。f
f
如果函数通过引用传递,则其声明为f
int f(car &c);
在本例中,
car carobj;
f(carobj);
不需要复制构造函数。
在本例中,成为 的别名。c
carobj
使用上述 2 种情况,为了您的清楚起见,我将它们总结为:
如果将函数声明为将参数作为对象的值,则调用该对象的复制构造函数。
如果将函数声明为将参数作为“通过引用传递”,则该参数将成为调用方提供的对象的别名。无需复制构造函数!
现在的问题是为什么需要通过引用传递。如果复制构造函数接受引用,则接收变量将成为所提供对象的别名。因此,无需复制构造函数(在本例中为调用自身)来复制调用方提供的对象中的值,即可在参数列表中复制构造函数的变量。
否则,如果复制构造函数将调用方提供的对象作为值,即按值传递,则它需要给定对象的复制构造函数;因此,为了将提供的对象从调用者获取到我们的函数本身(在本例中为 Copy 构造函数),我们需要调用 Copy 构造函数,这只不过是在函数声明中调用相同的函数。
这就是将引用传递给复制构造函数的原因。
评论
传递对象作为引用非常重要。如果将对象作为值传递给 Copy 构造函数,则其复制构造函数将调用自身,以将实际参数复制到形式参数。 因此,将启动对复制构造函数的无穷无尽的调用链。此过程将一直持续到系统内存不足为止。
因此,在复制构造函数中,参数应始终作为引用传递。
如果它不通过引用传递,那么它将通过值传递。如果参数按值传递,则其复制构造函数将调用自身以将实际参数复制到形式参数。此过程将持续到系统内存不足为止。 因此,我们应该通过引用传递它,以便复制构造函数不会被调用。
有必要将对象作为引用传递,而不是通过值传递,因为如果按值传递它,则其副本是使用 copy 构造函数构造的。这意味着 copy 构造函数将调用自身来进行复制。此过程将持续到编译器内存不足为止。
复制构造函数定义了复制的含义,因此,如果我们只传递一个对象(我们将传递该对象的副本),但要创建副本,我们将需要一个复制构造函数,因此它会导致无限递归。
因此,复制构造函数必须具有引用作为参数。
所有的答案都是正确的,但我想知道这些是否能帮助像我这样通过示例学习的初学者。所以,这里有一个例子。
以以下代码为例:
#include<iostream>
#include<cstring>
using namespace std;
class String
{
private:
char *s;
int size;
public:
String(const char *str)
{
size=strlen(str);
s=new char[size+1];
strcpy(s,str);
}
~String()
{
delete[] s;
}
String(const String& old_str)
{
size=old_str.size;
s=new char[size+1];
strcpy(s,old_str.s);
}
void print()
{
cout<<s<<endl;
}
void change(const char *str)
{
delete [] s;
size=strlen(str);
s=new char[size+1];
strcpy(s,str);
}
};
int main()
{
String str1("Hello World");
String str2=str1;
str1.print();
str2.print();
str2.change("Namaste");
str1.print();
str2.print();
return 0;
}
这是复制构造函数:
String(const String& old_str)
{
size=old_str.size;
s=new char[size+1];
strcpy(s,old_str.s);
}
想象一下,我们不通过引用。结婚
String(const String old_str)
{
size=old_str.size;
s=new char[size+1];
strcpy(s,old_str.s);
}
查看 int main() 函数。
String str2=str1
再次查看复制构造函数(无引用)。
String(const String old_str)
这意味着:
String old_str=str1
它基本上与 main() 函数中编写的内容相同。因此,它再次调用复制构造函数。在 C++ 中调用复制构造函数的规则是当你遇到这样的情况时:
ABC a;
ABC b=a;
我希望这会有所帮助。
评论