初始化列表:复制构造函数和赋值运算符=冗余?

发布于 2024-12-14 12:04:21 字数 693 浏览 1 评论 0原文

对于您的类构造函数来说,初始化列表似乎是一个好主意,我假设,对于复制构造函数也是如此。对于赋值运算符,必​​须对函数体中的每个成员进行赋值。考虑以下简单的块:

class Foo {
private: 
  int a,b;
public:
  Foo(int c, int d)  : a(c), b(d) {}
  Foo(const Foo & X) : a(X.a), b(X.b) {}
  Foo& operator=(const Foo& X) {
    if (this == &X) return *this;
    a = X.a;
    b = X.b;
    return *this;
  }
};

如果一个类具有适量的数据成员,则在三个地方可能会搞乱不同的分配/初始化。我的意思是,如果复制构造函数看起来像:

  Foo(const Foo & X) : a(X.a), b(X.a) {}

或者运算符 = 中缺少一行怎么办?由于赋值运算符和复制构造函数通常具有相同的效果(即我们将成员从一个 Foo 复制到另一个),我可以“重用”复制构造函数或赋值运算符中的代码,反之亦然吗?

It seems that initalizer lists are a good idea for your class constructors and, I'm assuming, for the copy constructor as well. For the assignment operator one has to assign each member in the body of the function. Consider the following simple block:

class Foo {
private: 
  int a,b;
public:
  Foo(int c, int d)  : a(c), b(d) {}
  Foo(const Foo & X) : a(X.a), b(X.b) {}
  Foo& operator=(const Foo& X) {
    if (this == &X) return *this;
    a = X.a;
    b = X.b;
    return *this;
  }
};

If a class has a moderate amount of data members, there are three places where one can mess up the the different assignments/initialization. By that I mean, what if the copy constructor looked like:

  Foo(const Foo & X) : a(X.a), b(X.a) {}

or a line was missing from the operator=. Since the assignment operator and the copy constructor often have the same effect (in that we copy members from one Foo to another) can I "reuse" the code from the copy constructor or the assignment operator or vice versa?

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

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

发布评论

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

评论(3

等数载,海棠开 2024-12-21 12:04:21

您的目标应该是根本不编写复制构造函数/赋值运算符。您的目标应该是让编译器完成它。标准库容器都是可复制的,因此请在合理的情况下使用它们。

如果存在无法正确复制的成员,则使用智能指针或其他 RAII 对象。这些对象应该需要特殊的复制构造函数/赋值。他们只需要他们的一名成员。

其他一切都不应该使用它们。

Your goal should be to not write copy constructors/assignment operators at all. Your goal should be to let the compiler do it. Standard library containers are all copyable, so use them where reasonable.

If there are members that cannot be copied correctly, then use smart pointers or other RAII objects. Those objects are the ones that should need special copy constructors/assignments. And they only need them for their one member.

Everything else should not use them.

稚气少女 2024-12-21 12:04:21

因为赋值运算符和复制构造函数通常具有相同的效果。

完全不是,一个进行初始化,另一个进行赋值。它们在对象的初始状态上是不同的,并且它们的任务是独立的(尽管相似)。规范的赋值运算符通常如下所示:

Foo& operator=(Foo right) {
    right.swap( *this );
    return *this;
}

Since the assignment operator and the copy constructor often have the same effect.

Not at all, one does initialization while the other does assignment. They are different in the initial state of the object, and their tasks are separate (though similar). The canonical assignment operator is usually done as:

Foo& operator=(Foo right) {
    right.swap( *this );
    return *this;
}
吾性傲以野 2024-12-21 12:04:21

将所有内容转发给赋值运算符可能无效,但这在允许这样做的 C++03 中很常见。

在 C++11 中,构造函数更容易:将所有构造函数转发给一个主构造函数。

class Foo {
private: 
  int a,b;
public:
  Foo(int c, int d)  : a(c), b(d) {}
  Foo(const Foo & X) : Foo(x.a, x.d) {} 
  //syntax may be wrong, I don't have a C++11 compiler
  Foo& operator=(const Foo& X) {
    if (this == &X) return *this;
    a = X.a;
    b = X.b;
    return *this;
  }
}

在 C++03 中(允许的地方)

class Foo {
private: 
  int a,b;
  void init(int c, int d) {a=c; b=d;}
public:
  Foo(int c, int d)  : {init(c,d);}
  Foo(const Foo & X) : {init(X.a, X.b);} 
  Foo& operator=(const Foo& X) { init(X.a, X.b);} 
}

但请记住,这不能在某些常见情况下使用。 (任何不可分配的对象)

It might not be valid to forward all to an assignment operator, but that is was commmon in C++03 where it was allowed.

In C++11 constructors are easier: forward all the constructors to one master constructor.

class Foo {
private: 
  int a,b;
public:
  Foo(int c, int d)  : a(c), b(d) {}
  Foo(const Foo & X) : Foo(x.a, x.d) {} 
  //syntax may be wrong, I don't have a C++11 compiler
  Foo& operator=(const Foo& X) {
    if (this == &X) return *this;
    a = X.a;
    b = X.b;
    return *this;
  }
}

In C++03 (where it is allowed)

class Foo {
private: 
  int a,b;
  void init(int c, int d) {a=c; b=d;}
public:
  Foo(int c, int d)  : {init(c,d);}
  Foo(const Foo & X) : {init(X.a, X.b);} 
  Foo& operator=(const Foo& X) { init(X.a, X.b);} 
}

But keep in mind that this cannot be used in some common cases. (any object that isn't assignable)

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