我是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;
}
详细阐述已经给出的两个答案:
当您将变量定义为与其他变量“相同”时,基本上有两种可能性:
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&传递只读参数。
因为通过值传递给函数意味着函数具有对象的自己的副本。为此,将调用复制构造函数。
void display(ClassA obj)
{
// display has its own ClassA object, a copy of the input
cout << "Hello World" << endl;
}
请记住,在某些情况下,例如,如果将临时值传递给函数,则可能会删除副本。
正如juanchopanza所说:您按值传递,这将导致复制。如果您想防止这种情况,可以通过引用传递:
void display(const ClassA &obj)
在旁注:您应该声明您的复制ctor以将参数用作const引用:
ClassA(const ClassA &obj)
否则,将无法在标记为const或临时名称的命名对象上使用复制ctor。它还可以防止您意外更改传入的对象。