C++ 当我们将对象作为参数按值传递给方法时,为什么会调用复制构造函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16728441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:35:41  来源:igfitidea点击:

Why is the copy constructor called when we pass an object as an argument by value to a method?

c++copy-constructorpass-by-value

提问by nagaradderKantesh

Why is the copy constructor called when I pass an object as an argument by value to a function? Please see my below code: I am passing an object of a class as an argument by value to a function display(), but it is calling the copy constructor before control is hitting the display()function. I don't understand why.

当我将对象作为参数按值传递给函数时,为什么会调用复制构造函数?请看我下面的代码:我将一个类的对象作为参数按值传递给一个函数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;
}

回答by Arne Mertz

To elaborate the two answers already given a bit:

详细说明已经给出的两个答案:

When you define variables to be "the same as" some other variable, you have basically two possibilities:

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

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

Instead of non-const lvalue references, there are of course const references and rvalue references. The main thing I want to point out here is, that aCopyis independent of someOtherA, while aRefis practically the same variable as someOtherA, it's just another name (alias) for it.

除了非常量左值引用,当然还有常量引用和右值引用。我想在这里指出的主要事情是,它aCopy独立于someOtherA,而aRef实际上与 相同的变量someOtherA,它只是它的另一个名称(别名)。

With function parameters, it's basically the same. When the parameter is a reference, it gets bound to the argument when the function is called, and it's just an alias for that argument. That means, what you do with the parameter, you do with the argument:

有了函数参数,基本是一样的。当参数是引用时,它会在函数被调用时绑定到参数,它只是该参数的别名。这意味着,你用参数做什么,你用参数做什么:

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

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

When the parameter is a value, it is only a copy of the argument, so regardless of what you do to the parameter, the argument remains unchanged.

当参数是一个值时,它只是参数的一个副本,所以无论你对参数做什么,参数都保持不变。

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

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

When you pass by value, the parameter is a new object. It has to be, since it's not the same as the argument, it's independent. Creating a new object that is a copy of the argument, means calling the copy constructor or move constructor, depending on whether the argument is an lvalue or rvalue. In your case, making the function pass by value is unnecessary, because you only read the argument.

按值传递时,参数是一个新对象。它必须是,因为它与参数不同,它是独立的。创建作为参数副本的新对象意味着调用复制构造函数或移动构造函数,具体取决于参数是左值还是右值。在您的情况下,不需要按值传递函数,因为您只读取参数。

There is a Guideline from GotW #4:

GotW #4有一个指南:

Prefer passing a read-only parameter by const& if you are only going to read from it (not make a copy of it).

如果您只想从中读取(而不是复制它),最好通过 const& 传递只读参数。

回答by juanchopanza

Because passing by value to a function means the function has its own copyof the object. To this end, the copy constructor is called.

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

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

Bear in mind that in some cases copies may be elided, for instance, if a temporary value is passed to the function.

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

回答by Tom

As juanchopanza said:, you pass by value, which causes a copy to be made. If you want to prevent this you can pass by reference:

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

void display(const ClassA &obj)

On a sidenote: You should declare your copy ctor to take the argument as const reference:

旁注:您应该声明您的复制构造函数以将参数作为常量引用:

ClassA(const ClassA &obj)

Otherwise you won't be able to use the copy ctor on named objects marked as const or with temporaries. It also prevents you from accidentally changing the passed in object.

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