C ++有两个拷贝构造函数,都是通过引用和值?

时间:2011-12-08 19:58:00

标签: c++ copy-constructor

考虑这段代码:

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中,允许这样做,因为它只是将对象复制到构造函数中。

3 个答案:

答案 0 :(得分:3)

复制构造函数必须处于以下形式:

T(T&);
T(const T&);

也就是说,如果构造函数采用引用类类型的单个参数,则构造函数是复制构造函数 。根据定义,采用类型类型的单个参数的构造函数不是复制构造函数(编辑) - 实际上是非法的,正如Cat Plus Plus所指出的那样。

12.1:构造函数

  

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 ++中那样调用复制构造函数。