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

发布于 2024-12-20 18:35:40 字数 556 浏览 1 评论 0原文

考虑这段代码:

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

Consider this piece of code:

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){}
};

I already knew that the copy constructor complex(complex c) will cause infinite recursion.

However, it should only pick const reference copy constructor complex(const complex &c) as the function for copying, since this is the default behavior if it is not explicitly specified. Every thing else is excluded, such as complex(complex c).

Why does it apply the function with pass by value here? Or both are copy constructors, except the pass by value cannot be modified and is used to pass to other functions rather than its constructor?

I think in Java, it is permitted to do like that, since it will just copy the object into the constructor.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

铜锣湾横着走 2024-12-27 18:35:40

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

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。所以,你看这里有一个悖论。为了调用复制构造函数,您必须进行复制。为了进行复制,您必须调用复制构造函数...

上面的代码必须使用参数按值调用构造函数,因为这就是参数的类型:它是一个 < code>Foo 按值。如果它不是按值,则必须通过引用,如下所示:

Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);

...或者必须通过指针获取它,如下所示:

Foo(Foo* prhs)

...但是,在后一种情况下,这是根据上面的定义,显然不是复制构造函数。

A copy constructor must be in on of the following forms:

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

That is, a constructor is a copy constructor only if it takes a single parameter of reference class type. A constructor that takes a single parameter of class type by-value is, by definition, not a copy constructor (edit) -- and in fact is illegal, as pointed out by Cat Plus Plus.

12.1 : Constructors

10/A copy constructor for a class X is a constructor with a first parameter of type X& or of type const X&

Beyond this Standardese, however, is a fundamental error in your understanding of the copy constructor. Consider the following code:

class Foo
{
public:
  Foo() {}
  Foo(Foo f) {/*...*/};
};

int main()
{
  Foo f1;
  Foo f2(f1);
}

When f2 is constructed f1 is passed by-value. In order to evaluate the parameters for the constructor call, f1 must be copied. So, you see there is a paradox here. In order to call the copy constructor, you must make a copy. In order to make a copy, you must call the copy constructor...

The above must call the constructor with an argument by-value simply because that is what the type of the parameter is: it's a Foo by-value. It it were not by-value, it would have to be either by reference, which looks like this:

Foo(Foo& rhs)
/* or like this: */ Foo(const Foo& rhs);

...or it must take it by pointer, which looks like this:

Foo(Foo* prhs)

...but, in the latter case, this is obviously not a copy constructor given the definition above.

乜一 2024-12-27 18:35:40

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

如果类 X 的第一个参数的类型为 X&、const X&、volatile X&,则类 X 的非模板构造函数是复制构造函数。或 const 易失性 X&,并且要么没有其他参数,要么所有其他参数都有默认参数 (8.3.6)。

如果类 X 的第一个参数是类型(可选 cv 限定的),则该类的构造函数的声明是格式错误的
X 并且要么没有其他参数,要么所有其他参数都有默认参数。会员
函数模板永远不会实例化以产生这样的构造函数签名。

complex(complex) is not a copy constructor. It's ill-formed, and should be rejected by compiler. There is no infinite recursion, because you simply cannot define a constructor like that.

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6).

A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified)
X and either there are no other parameters or else all other parameters have default arguments. A member
function template is never instantiated to produce such a constructor signature.

怪我太投入 2024-12-27 18:35:40

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

Answer to Java question since all other possible explanations are given:

//java code

public class Bar{
  private int foo;

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

In Java objects are references and not value objects like they are in C++. In C++ when you copy an object you create a copy of the object's state, internal variables etc. In Java it simply copies the reference. The object's state is not copied so there is actually no need to call the copy constructor like you do it in C++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文