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