C++有两个复制构造函数,分别是引用和值?

C++有两个复制构造函数,分别是引用和值?,c++,copy-constructor,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){} }; 我已经知道复制构造函数complexcomplexC将导致无限递归 但是,它

考虑这段代码:

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){}
};
我已经知道复制构造函数complexcomplexC将导致无限递归

但是,它应该只选择const reference copy constructor complexconst complex&c作为复制函数,因为如果没有明确指定,这是默认行为。所有其他的东西都被排除在外,比如complexcomplex c


为什么它在这里应用带传递值的函数?或者两者都是复制构造函数,除非传递值不能修改,并且用于传递给其他函数而不是其构造函数

我认为在Java中,可以这样做,因为它只会将对象复制到构造函数中。

复制构造函数必须采用以下形式之一:

T(T&);
T(const T&);
也就是说,只有当构造函数接受引用类类型的单个参数时,它才是复制构造函数。根据定义,按值获取类类型的单个参数的构造函数不是复制构造函数编辑-事实上,正如Cat 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。你看,这里有一个悖论。为了调用复制构造函数,必须创建一个副本。为了创建副本,必须调用副本构造函数

上面必须使用参数by value调用构造函数,因为这就是参数的类型:它是Foo by value。如果不是通过值,则必须通过引用,如下所示:

Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);
Foo(Foo* prhs)
…或者它必须通过指针获取,如下所示:

Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);
Foo(Foo* prhs)
…但是,在后一种情况下,根据上述定义,这显然不是复制构造函数。

复制构造函数必须采用以下形式之一:

T(T&);
T(const T&);
也就是说,只有当构造函数接受引用类类型的单个参数时,它才是复制构造函数。根据定义,按值获取类类型的单个参数的构造函数不是复制构造函数编辑-事实上,正如Cat 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。你看,这里有一个悖论。为了调用复制构造函数,必须创建一个副本。为了创建副本,必须调用副本构造函数

上面必须使用参数by value调用构造函数,因为这就是参数的类型:它是Foo by value。如果不是通过值,则必须通过引用,如下所示:

Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);
Foo(Foo* prhs)
…或者它必须通过指针获取,如下所示:

Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);
Foo(Foo* prhs)
…但是,在后一种情况下,根据上述定义,这显然不是复制构造函数。

complexcomplex不是复制构造函数。它的格式不正确,应该被编译器拒绝。不存在无限递归,因为您根本无法定义这样的构造函数

如果类X的非模板构造函数的第一个参数类型为X&、常量X&、volatile X&或const volatile X&,并且没有其他参数,或者所有其他参数都有默认参数,则该类X的非模板构造函数为复制构造函数8.3.6

如果类X的构造函数的第一个参数的类型为可选cv限定,则该类X的构造函数声明的格式是错误的 X,或者没有其他参数,或者所有其他参数都有默认参数。成员 函数模板从未实例化以生成这样的构造函数签名

complexcomplex不是复制构造函数。它的格式不正确,应该被编译器拒绝。不存在无限递归,因为您根本无法定义这样的构造函数

如果类X的非模板构造函数的第一个参数类型为X&、常量X&、volatile X&或const volatile X&,并且没有其他参数,或者所有其他参数都有默认参数,则该类X的非模板构造函数为复制构造函数8.3.6

如果类X的构造函数的第一个参数的类型为可选cv限定,则该类X的构造函数声明的格式是错误的 X,或者没有其他参数,或者所有其他参数都有默认参数。成员 函数模板从未实例化以生成这样的构造函数签名


Java问题的答案,因为所有其他可能的解释 这些数字如下:

//java code

public class Bar{
  private int foo;

  public Bar() { } // public no-args constructor
  public Bar(Bar b) { foo = b.foo; }  // copy constructor
}

<爪哇>对象是引用,而不是值对象,就像它们是C++一样。在C++中,当你复制一个对象时,你会创建一个对象的状态、内部变量等的拷贝。java中,它只是复制引用。对象的状态不被复制,所以实际上不需要调用复制构造函数,就像在C++中那样做。

< p>回答java问题,因为给出了所有其他可能的解释:

//java code

public class Bar{
  private int foo;

  public Bar() { } // public no-args constructor
  public Bar(Bar b) { foo = b.foo; }  // copy constructor
}


<爪哇>对象是引用,而不是值对象,就像它们是C++一样。在C++中,当你复制一个对象时,你会创建一个对象的状态、内部变量等的拷贝。java中,它只是复制引用。对象的状态不被复制,所以实际上不需要调用C++构造函数,就像C++中的那样。

您可能需要添加我从上一个问题给出的示例:FieldFieldC和CopyNoistSoad。为什么它在这里使用带值的函数?这个问题缺少什么吗?@pmr指的是我前一个问题,因为有太多重复的问题,不久前这个问题就结束了:@pmr我想OP是在问重载是否有效:complexcomplex c和complexconst complex&c,如果有效,将会发生什么。您可能想添加我在上一个问题中给出的示例:complexcomplex c和complexconst complex&cWhy它在这里应用带传递值的函数?这个问题缺少什么吗?@pmr指的是我前一个问题,因为有太多重复的问题,不久前这个问题就结束了:@pmr我想OP是在问重载是否有效:complexcomplex c和complexconst complex&c,如果有效,将会发生什么。他已经知道通过值传递会导致无限递归。啊,这是两个函数调用之间的模糊性,因为通过ref或通过值传递,调用方使用相同的函数调用。编译器会出错并调用按值复制构造函数。我的理解正确吗?@Amumu不,编译器不会使用按值获取参数的复制构造函数编译代码,或者至少不应该这样做,不管是否这样都是另一个问题。@Seth是的,编译器会错误地调用错误的函数,然后产生错误。我认为在早期它将允许编译这个符号,正如您所说的,甚至VS也允许。问题的关键是我想知道为什么。@Amumu:没有按值复制构造函数。他已经知道按值传递会导致无限递归。啊,这就是两个函数调用之间的模糊性,因为按引用传递或按值传递,调用方使用相同的函数调用。编译器会出错并调用按值复制构造函数。我的理解正确吗?@Amumu不,编译器不会使用按值获取参数的复制构造函数编译代码,或者至少不应该这样做,不管是否这样都是另一个问题。@Seth是的,编译器会错误地调用错误的函数,然后产生错误。我认为在早期它将允许编译这个符号,正如您所说的,甚至VS也允许。问题的关键是我想知道为什么。@Amumu:没有按值复制的构造函数。g++会拒绝它吗?我知道VS不允许,但为什么不允许呢?在Java中,正如我所记得的,它是。@SethCarnegie它做MSVS2010SP1@Amumu因为它没有意义,如果你这样做,那么要复制一个对象,你必须先复制一个对象。同样,在Java中,你不按值传递东西,所有的对象都是按引用传递的,所以不,在Java中甚至不是这样。@SethCarnegie不,几乎所有的东西都是引用。但是,这些引用是按值传递的。g++是否拒绝它?我知道VS不允许,但为什么不允许呢?在Java中,正如我所记得的,它是。@SethCarnegie它做MSVS2010SP1@Amumu因为它没有意义,如果你这样做,那么要复制一个对象,你必须先复制一个对象。同样,在Java中,你不按值传递东西,所有的对象都是按引用传递的,所以不,在Java中甚至不是这样。@SethCarnegie不,几乎所有的东西都是引用。但是,这些引用是按值传递的。Java的复制构造函数实际上是Object.clone。是的,但我认为OP指的是这个。你是对的。我忘了Java是对象的按引用传递。Java的复制构造函数实际上是Object.clone。是的,但我认为OP指的是这个。你是对的。我忘了Java是对象的按引用传递的。