当我们通过值将对象作为参数传递给方法时,为什么调用复制构造函数

问题描述 投票:13回答:3

我是C ++编程的新手,在执行某些C ++程序时,我有一个疑问,那就是为什么当我将一个对象作为值作为参数传递给函数时,调用复制构造函数的原因。请参阅下面的代码,因为我将类的对象作为值作为参数传递给函数display(),但是它调用了复制构造函数,然后控件击中了display()函数,但是我了解为什么,所以请帮忙。

#include "stdafx.h"
#include <iostream>
using namespace std;

class ClassA
{
    private:
       int a, b;
    public:
       ClassA()
       {
           a = 10, b = 20;
       }
       ClassA(ClassA &obj)
       {
           cout << "copy constructor called" << endl;
           a = obj.a;
           b = obj.b;
       }
};
void display(ClassA obj)
{
   cout << "Hello World" << endl;
}
int main()
{
   ClassA obj;
   display(obj);
   return 0;
}
c++ copy-constructor pass-by-value
3个回答
16
投票

详细阐述已经给出的两个答案:

当您将变量定义为与其他变量“相同”时,基本上有两种可能性:

ClassA aCopy = someOtherA; //copy
ClassA& aRef = someOtherA; //reference

当然有const引用和rvalue引用,而不是非const左值引用。我要在这里指出的主要问题是,aCopy独立于someOtherA,而aRef实际上是与someOtherA相同的变量,只是它的另一个名称(别名)。

使用功能参数,基本上是相同的。如果参数是引用,则在调用函数时它将绑定到参数,并且它只是该参数的别名。这就是说,您对参数执行的操作,对参数执行的操作:

void f(int& iRef) {
  ++iRef;
}

int main() {
  int i = 5;
  f(i); //i becomes 6, because iRef IS i
}

[当参数是一个值时,它只是参数的一个副本,因此无论您对参数执行什么操作,参数都保持不变。

void f(int iCopy) {
  ++iCopy;
}

int main() {
  int i = 5;
  f(i); //i remains 5, because iCopy IS NOT i
}

当按值传递时,参数是一个新对象。由于它与参数不同,因此必须是独立的。创建一个新对象作为参数的副本,这意味着调用副本构造函数或移动构造函数,具体取决于参数是左值还是右值。就您而言,使函数按值传递是不必要的,因为您只读取了参数。

有一个GotW #4的指南:

如果只想从常量(而不是它的副本)中读取,则最好通过const&传递只读参数。


5
投票

因为通过值传递给函数意味着函数具有对象的自己的副本。为此,将调用复制构造函数。

void display(ClassA obj)
{
   // display has its own ClassA object, a copy of the input
   cout << "Hello World" << endl;
}

请记住,在某些情况下,例如,如果将临时值传递给函数,则可能会删除副本。


3
投票

正如juanchopanza所说:您按值传递,这将导致复制。如果您想防止这种情况,可以通过引用传递:

void display(const ClassA &obj)

在旁注:您应该声明您的复制ctor以将参数用作const引用:

ClassA(const ClassA &obj)

否则,将无法在标记为const或临时名称的命名对象上使用复制ctor。它还可以防止您意外更改传入的对象。

© www.soinside.com 2019 - 2024. All rights reserved.