考虑这段代码:
class complex{
private:
double re, im;
public:
complex(double _re, double _im):re(_re),im(_im){}
complex(complex c):re(c.re),im(c.im){}
};
我已经知道复制构造函数complex(complex c)
将导致无限递归。
但是,它应该只选择const引用复制构造函数complex(const complex &c)
作为复制函数,因为如果没有明确指定它,这是默认行为。其他所有内容都被排除在外,例如complex(complex c)
。
为什么在这里应用带值传递的函数?或者两者都是复制构造函数,除了传递值不能被修改并用于传递给其他函数而不是它的构造函数?
我认为在Java中,允许这样做,因为它只是将对象复制到构造函数中。
答案 0 :(得分:3)
复制构造函数必须处于以下形式:
T(T&);
T(const T&);
也就是说,如果构造函数采用引用类类型的单个参数,则构造函数是复制构造函数 。根据定义,采用类型类型的单个参数的构造函数不是复制构造函数(编辑) - 实际上是非法的,正如Cat Plus Plus所指出的那样。
10 /类X的复制构造函数是一个构造函数,其第一个参数类型为X&或类型为const X&
然而,除了这个标准之外,你理解复制构造函数是一个根本性错误。请考虑以下代码:
class Foo
{
public:
Foo() {}
Foo(Foo f) {/*...*/};
};
int main()
{
Foo f1;
Foo f2(f1);
}
构造f2
f1
时,按值传递f1
。为了评估构造函数调用的参数,必须复制Foo
。所以,你看到这里有一个悖论。要调用复制构造函数,您必须复制。要制作副本,您必须调用复制构造函数...
上面必须使用参数by-value调用构造函数,因为这是参数的类型:它是一个Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);
by-value。它不是按价值,它必须是参考,看起来像这样:
Foo(Foo* prhs)
...或者它必须通过指针来看,它看起来像这样:
{{1}}
...但是,在后一种情况下,根据上面的定义,这显然不是复制构造函数。
答案 1 :(得分:2)
complex(complex)
不是复制构造函数。它的结构不合理,应该被编译器拒绝。没有无限递归,因为你根本无法定义这样的构造函数。
类X的非模板构造函数是复制构造函数,如果它的第一个参数是X&类型,const X&,volatile X&或const volatile X&,并且没有其他参数,或者所有其他参数都有默认参数(8.3.6)。
如果类X的构造函数的第一个参数类型(可选择cv-quali fi ed),则它的构造函数声明格式不正确 X并且没有其他参数,否则所有其他参数都有默认参数。成员 函数模板永远不会被实例化以生成这样的构造函数签名。
答案 2 :(得分:1)
回答Java问题,因为给出了所有其他可能的解释:
//java code
public class Bar{
private int foo;
public Bar() { } // public no-args constructor
public Bar(Bar b) { foo = b.foo; } // copy constructor
}
在Java对象中是引用而不是像C ++中那样的值对象。在C ++中复制对象时,您可以创建对象状态,内部变量等的副本。在Java中,它只是复制引用。不会复制对象的状态,因此实际上不需要像在C ++中那样调用复制构造函数。