Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么复制构造函数要在C+;中通过引用接受其参数+;?_C++_Constructor_Copy_Copy Constructor - Fatal编程技术网

C++ 为什么复制构造函数要在C+;中通过引用接受其参数+;?

C++ 为什么复制构造函数要在C+;中通过引用接受其参数+;?,c++,constructor,copy,copy-constructor,C++,Constructor,Copy,Copy Constructor,为什么复制构造函数的参数必须通过引用传递?因为如果不是通过引用传递,则是通过值传递。为此,您创建了一个副本,并为此调用了复制构造函数。但要做到这一点,我们需要创建一个新值,所以我们调用复制构造函数,等等 (您将具有无限递归,因为“要创建副本,您需要创建副本”。因为pass-by-value将调用复制构造函数:)如果您按值传递它,它将是无限递归的。传递值实际上是传递副本。复制构造函数是制作副本所必需的 如果为了调用复制构造函数而必须进行复制,这将是一个难题 (我认为无限递归会发生在编译器中,你永远

为什么复制构造函数的参数必须通过引用传递?

因为如果不是通过引用传递,则是通过值传递。为此,您创建了一个副本,并为此调用了复制构造函数。但要做到这一点,我们需要创建一个新值,所以我们调用复制构造函数,等等


(您将具有无限递归,因为“要创建副本,您需要创建副本”。

因为pass-by-value将调用复制构造函数:)

如果您按值传递它,它将是无限递归的。传递值实际上是传递副本。复制构造函数是制作副本所必需的

如果为了调用复制构造函数而必须进行复制,这将是一个难题

(我认为无限递归会发生在编译器中,你永远不会得到这样一个程序。)

除合理原因外,§12.8/3中的标准禁止:

函数的构造函数的声明 如果类X的第一个 参数的类型为(可选为cv)- 合格)X,并且没有 其他参数或其他所有参数 参数具有默认参数


无论何时调用函数(例如:intf(carc)) 它接受的参数不是内置的数据类型(这里是car) 复制调用方提供的实际对象的要求 调用函数参数中的变量。
例如:

carobj;
f(carobj)

也就是说,将
carobj
复制到
c

carobj
需要复制到函数
f
中的参数
c

为了实现复制,调用复制构造函数

在这种情况下,使用传递值调用函数
f
,或者换句话说,函数
f
被声明为接受传递值

如果函数
f
通过引用传递,则其声明为
intf(car&c)

在这种情况下,
carobj;
f(carobj)

不需要复制构造函数

在这种情况下,
c
成为
carobj
的别名

使用上述两种情况,为便于澄清,我将其总结为:

  • 如果函数声明以参数作为对象的值,则调用该对象的复制构造函数

  • 如果函数声明将参数作为“按引用传递”,则该参数将成为调用者提供的对象的别名。不需要复制构造函数

  • 现在的问题是为什么需要通过引用传递。如果复制构造函数接受引用,则接收变量将成为所提供对象的别名。因此,不需要复制构造函数(在本例中是对自身的调用)将调用者提供的对象中的值复制到参数列表中的构造函数变量

    否则,如果复制构造函数将调用方提供的对象作为值,即传递值,则需要给定对象的复制构造函数;因此,要将调用方提供的对象放入函数本身(在本例中为复制构造函数),我们需要调用复制构造函数,它只是在函数声明期间调用同一个函数


    这就是将引用传递给副本构造函数的原因。

    将对象作为引用传递是非常必要的。如果将对象作为值传递给复制构造函数,则其复制构造函数将调用自身,将实际参数复制到形式参数。 因此,将启动对复制构造函数的无休止的调用链。此过程将一直持续到系统内存耗尽


    因此,在复制构造函数中,参数应始终作为引用传递。

    如果它不是通过引用传递的,则它将通过值传递。如果参数是按值传递的,则其复制构造函数将调用自身将实际参数复制到形式参数。这个过程将一直持续到系统内存不足为止。
    所以,我们应该通过引用传递它,这样复制构造函数就不会被调用

    有必要将对象作为引用传递,而不是按值传递,因为如果按值传递,则其副本是使用复制构造函数构造的。这意味着复制构造函数将调用自身进行复制。此过程将一直进行,直到编译器内存耗尽。

    编译器可以愉快地抛出无限递归;我怀疑这不是特例。但是,如果使用非引用参数声明副本构造函数,则程序的格式不正确。所以你说它不应该编译是对的。@Dennis:我的意思是,如果你试图编译这样一个程序,编译器在试图生成代码时会陷入困境。它不会生成递归函数,因为这个难题发生在函数调用之前,在调用方中。不管怎样,无论您是否尝试使用它,程序都是格式错误的。简单地定义构造函数就足以让编译器对你大喊大叫。@Dennis:的确,尽管这只是一条规则。有没有理由不能通过指针传递到实例?那么它就不再是复制构造函数了,但是只是一个普通的旧构造函数,它碰巧接受一个指针。@巴里当编译器试图通过调用
    object o(other\u object)
    来自己复制一个对象时,通常会实现一个复制构造函数。但只有当
    对象
    有一个构造函数通过值或引用获取另一个
    对象时,这才有效。您已经知道为什么按值传递不起作用,所以唯一的方法是按引用或常量引用传递。如果您的“复制构造函数”将获取指向
    对象的指针
    ,那么编译器的代码必须是
    对象o(&other_object)
    。因此,本质上,您编写的构造函数满足编译器和用户的期望。是的,这是完全有意义的。谢谢。另一个很好的理由,由