根据operator=实现复制构造函数

发布于 2024-09-18 01:46:51 字数 149 浏览 2 评论 0原文

如果 operator= 定义正确,是否可以使用以下内容作为复制构造函数?

MyClass::MyClass(MyClass const &_copy)
{
    *this = _copy;
}

If the operator= is properly defined, is it OK to use the following as copy constructor?

MyClass::MyClass(MyClass const &_copy)
{
    *this = _copy;
}

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

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

发布评论

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

评论(8

橘寄 2024-09-25 01:46:52

是的。

就我个人而言,如果你的类没有指针,尽管我不会重载等于运算符或编写复制构造函数并让编译器为你做这件事;它将实现浅复制,您将确定所有成员数据都被复制,而如果您重载 = op;然后添加一个数据成员,然后忘记更新重载,你就会遇到问题。

yes.

personally, if your class doesn't have pointers though I'd not overload the equal operator or write the copy constructor and let the compiler do it for you; it will implement a shallow copy and you'll know for sure that all member data is copied, whereas if you overload the = op; and then add a data member and then forget to update the overload you'll have a problem.

橙味迷妹 2024-09-25 01:46:52

@Alexandre - 我不确定在赋值运算符中按值传递。在那里调用复制构造函数有什么好处?这会紧固赋值运算符吗?

PS我不知道怎么写评论。或者可能是我不被允许写评论。

@Alexandre - I am not sure about passing by value in assignment operator. What is the advantage you will get by calling copy constructor there? Is this going to fasten the assignment operator?

P.S. I don't know how to write comments. Or may be I am not allowed to write comments.

笨笨の傻瓜 2024-09-25 01:46:52

如果您有一个有效的赋值运算符(复制运算符),那么从技术上讲,这是可以的。

但是,您应该更喜欢复制和交换,因为:

  • 使用复制交换可以更轻松地实现异常安全
  • 最符合逻辑的关注点分离
    • 复制因子的作用是分配它所需的资源(以复制其他内容)。
    • 交换函数(大部分)用于交换内部“句柄”,不需要进行资源分配(取消)分配
    • 析构函数与资源释放有关
    • 复制和交换自然地将这三个函数结合在赋值/复制运算符中

It is technically OK, if you have a working assignment operator (copy operator).

However, you should prefer copy-and-swap because:

  • Exception safety is easier with copy-swap
  • Most logical separation of concerns:
    • The copy-ctor is about allocating the resources it needs (to copy the other stuff).
    • The swap function is (mostly) only about exchanging internal "handles" and doesn't need to do resource (de)allocation
    • The destructor is about resource deallocation
    • Copy-and-swap naturally combines these three function in the assignment/copy operator
嗼ふ静 2024-09-25 01:46:51

如果 MyClass 的所有成员都有默认构造函数,那么是的。

请注意,通常情况是相反的:

class MyClass
{
public:
    MyClass(MyClass const&);     // Implemented
    void swap(MyClass&) throw(); // Implemented
    MyClass& operator=(MyClass rhs) { rhs.swap(*this); return *this; }
};

我们在 operator= 中传递值,以便调用复制构造函数。请注意,一切都是异常安全的,因为 swap 保证不会抛出(您必须在实现中确保这一点)。

根据要求编辑关于按值调用的内容:operator= 可以这样编写,因为

MyClass& MyClass::operator=(MyClass const& rhs)
{
    MyClass tmp(rhs);
    tmp.swap(*this);
    return *this;
}

C++ 学生通常被告知通过引用传递类实例,因为如果通过传递类实例,则复制构造函数会被调用价值。在我们的例子中,无论如何我们都必须复制 rhs,所以按值传递是可以的。

因此,operator=(第一个版本,按值调用)读取:

  • 制作 rhs 的副本(通过复制构造函数,自动调用)
  • 将其内容与 交换*this
  • 返回*this 并让rhs(包含旧值)在方法退出时被销毁。

现在,我们通过这种按值调用获得了额外的好处。如果传递给 operator= 的对象(或任何通过值获取其参数的函数)是一个临时对象,编译器可以(并且通常)在以下位置不进行复制:全部。这称为复制省略

因此,如果 rhs 是临时的,则不会进行任何复制。我们剩下:

  • 交换 thisrhs 内容
  • 销毁 rhs

因此,在这种情况下,按值传递高效而不是通过引用传递。

If all members of MyClass have a default constructor, yes.

Note that usually it is the other way around:

class MyClass
{
public:
    MyClass(MyClass const&);     // Implemented
    void swap(MyClass&) throw(); // Implemented
    MyClass& operator=(MyClass rhs) { rhs.swap(*this); return *this; }
};

We pass by value in operator= so that the copy constructor gets called. Note that everything is exception safe, since swap is guaranteed not to throw (you have to ensure this in your implementation).

EDIT, as requested, about the call-by-value stuff: The operator= could be written as

MyClass& MyClass::operator=(MyClass const& rhs)
{
    MyClass tmp(rhs);
    tmp.swap(*this);
    return *this;
}

C++ students are usually told to pass class instances by reference because the copy constructor gets called if they are passed by value. In our case, we have to copy rhs anyway, so passing by value is fine.

Thus, the operator= (first version, call by value) reads:

  • Make a copy of rhs (via the copy constructor, automatically called)
  • Swap its contents with *this
  • Return *this and let rhs (which contains the old value) be destroyed at method exit.

Now, we have an extra bonus with this call-by-value. If the object being passed to operator= (or any function which gets its arguments by value) is a temporary object, the compiler can (and usually does) make no copy at all. This is called copy elision.

Therefore, if rhs is temporary, no copy is made. We are left with:

  • Swap this and rhs contents
  • Destroy rhs

So passing by value is in this case more efficient than passing by reference.

蓝天白云 2024-09-25 01:46:51

更建议根据异常安全复制构造函数来实现operator=。请参阅 Herb Sutter 的示例 4,了解该技术的解释以及为什么这是一个好主意。

http://www.gotw.ca/gotw/059.htm

It is more advisable to implement operator= in terms of an exception safe copy constructor. See Example 4. in this from Herb Sutter for an explanation of the technique and why it's a good idea.

http://www.gotw.ca/gotw/059.htm

↘人皮目录ツ 2024-09-25 01:46:51

此实现意味着所有数据成员(和基类)的默认构造函数都可以从 MyClass 中使用和访问,因为在进行赋值之前将首先调用它们。即使在这种情况下,对构造函数的额外调用也可能会很昂贵(取决于类的内容)。

我仍然会坚持通过初始化列表单独实现复制构造函数,即使这意味着编写更多代码。

另一件事:此实现可能会产生副作用(例如,如果您有动态分配的成员)。

This implementation implies that the default constructors for all the data members (and base classes) are available and accessible from MyClass, because they will be called first, before making the assignment. Even in this case, having this extra call for the constructors might be expensive (depending on the content of the class).

I would still stick to separate implementation of the copy constructor through initialization list, even if it means writing more code.

Another thing: This implementation might have side effects (e.g. if you have dynamically allocated members).

笑咖 2024-09-25 01:46:51

虽然最终结果是相同的,但成员首先被默认初始化,然后才被复制。

对于“昂贵”的成员,您最好使用初始值设定项列表进行复制构造。

struct C {
   ExpensiveType member;

   C( const C& other ): member(other.member) {}
};



 };

While the end result is the same, the members are first default initialized, only copied after that.

With 'expensive' members, you better copy-construct with an initializer list.

struct C {
   ExpensiveType member;

   C( const C& other ): member(other.member) {}
};



 };
冰魂雪魄 2024-09-25 01:46:51

我想说如果 MyClass 分配内存或者是可变的,这是不行的。

I would say this is not okay if MyClass allocates memory or is mutable.

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