C++核心准则C.60: 拷贝赋值运算符应该是以const&为参数,返回非常...

共 3164字,需浏览 7分钟

 ·

2020-01-08 23:22

c2bcf90cb6bbf6609e406f95d65c7d21.webp

C.60: Make copy assignment non-virtual, take the parameter by const&, and return by non-const&
C.60: 拷贝赋值运算符应该是以const&为参数,返回非常量引用类型的非虚函数


Reason(原因)

It is simple and efficient. If you want to optimize for rvalues, provide an overload that takes a && (see F.18).

因为这样简单且高效。如果你希望对右值优化,提供一个使用&&(右值引用)的重载。


Example(示例)

class Foo {
public:
   Foo& operator=(const Foo& x)
   {
       // GOOD: no need to check for self-assignment (other than performance)
       auto tmp = x;
       swap(tmp); // see C.83
       return *this;
   }
   // ...
};

Foo a;
Foo b;
Foo f();

a = b;    // assign lvalue: copy
a = f();  // assign rvalue: potentially move

Note(注意)

The swap implementation technique offers the strong guarantee.

实现交换函数(参考C.83)的技术提供了(不会发生自拷贝,译者注)强有力的保证。


Example(示例)

But what if you can get significantly better performance by not making a temporary copy? Consider a simple Vector intended for a domain where assignment of large, equal-sized Vectors is common. In this case, the copy of elements implied by the swap implementation technique could cause an order of magnitude increase in cost:

但是能不能通过少进行一次临时的拷贝动作来得到明显更高的性能呢?考虑用于(元素,译者注)大小相同的巨大Vector赋值的简单的Vector的场景。在这种情况下,通过swap技术实现的元素拷贝动作将引起成本的大幅度增加。


译者注

前面的例子,在swap之前进行了一次拷贝构造

template
class Vector {
public:
   Vector& operator=(const Vector&);
   // ...
private:
   T* elem;
   int sz;
};

Vector& Vector::operator=(const Vector& a)
{
   if (a.sz > sz) {
       // ... use the swap technique, it can't be bettered ...
       return *this;
   }
   // ... copy sz elements from *a.elem to elem ...
   if (a.sz < sz) {
       // ... destroy the surplus elements in *this and adjust size ...
   }
   return *this;

By writing directly to the target elements, we will get the basic guarantee rather than the strong guarantee offered by the swap technique. Beware of self-assignment.

通过将数据直接写入对象元素,我们可以得到基本的保证而不是通过swap技术提供的强保证。为了防止自己给自己赋值。


Alternatives(可选项)

If you think you need a virtual assignment operator, and understand why that's deeply problematic, don't call it operator=. Make it a named function like virtual void assign(const Foo&). See copy constructor vs. clone().

如果你认为你需要一个虚赋值操作运算符,而且理解它会产生很深刻的问题,别把设计成赋值运算符。将它定义为具名函数,例如virtual void assign(const Foo&)。参考【拷贝构造函数vs克隆】。


拷贝构造vs克隆的链接:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-copy-virtual


Enforcement(实施建议)

  • (Simple) An assignment operator should not be virtual. Here be dragons!

    (简单)赋值运算符不应该是虚函数。那样做很危险。

  • (Simple) An assignment operator should return T& to enable chaining, not alternatives like const T& which interfere with composability and putting objects in containers.

    (简单)赋值运算符应该返回T&,这样才能实现连续赋值。不要改成类似const T&的类型,这样会影响组装性并妨碍将对象放进容器中。

  • (Moderate) An assignment operator should (implicitly or explicitly) invoke all base and member assignment operators. Look at the destructor to determine if the type has pointer semantics or value semantics.

    (中等)赋值运算符应该(隐式或显式)调用所有的基类和成员的赋值运算符。观察析构函数以决定这个类型式指针语义还是值语义。

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c60-make-copy-assignment-non-virtual-take-the-parameter-by-const-and-return-by-non-const




觉得本文有帮助?请分享给更多人。

关注【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!


浏览 9
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报