c – 为什么使用处理复制和移动分配的单个赋值运算符效率不高?

前端之家收集整理的这篇文章主要介绍了c – 为什么使用处理复制和移动分配的单个赋值运算符效率不高?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
以下是C Primer第5版的练习:

Exercise 13.53:
As a matter of low-level efficiency,the HasPtr
assignment operator is not ideal. Explain why. Implement a
copy-assignment and move-assignment operator for HasPtr and compare
the operations executed in your new move-assignment operator versus
the copy-and-swap version.(P.544)

@H_403_14@

文件hasptr.h:

  1. //! a class holding a std::string*
  2. class HasPtr
  3. {
  4. friend void swap(HasPtr&,HasPtr&);
  5. friend bool operator <(const HasPtr& lhs,const HasPtr& rhs);
  6. public:
  7. //! default constructor.
  8. HasPtr(const std::string &s = std::string()):
  9. ps(new std::string(s)),i(0)
  10. { }
  11.  
  12. //! copy constructor.
  13. HasPtr(const HasPtr& hp) :
  14. ps(new std::string(*hp.ps)),i(hp.i)
  15. { }
  16.  
  17. //! move constructor.
  18. HasPtr(HasPtr&& hp) noexcept :
  19. ps(hp.ps),i(hp.i)
  20. { hp.ps = nullptr; }
  21.  
  22. //! assignment operator
  23. HasPtr&
  24. operator = (HasPtr rhs);
  25.  
  26. //! destructor.
  27. ~HasPtr()
  28. {
  29. delete ps;
  30. }
  31.  
  32. private:
  33. std::string *ps;
  34. int i;
  35. };

hasptr.cpp文件的一部分:

  1. //! specific swap.
  2. inline void
  3. swap(HasPtr &lhs,HasPtr &rhs)
  4. {
  5. using std::swap;
  6. swap(lhs.ps,rhs.ps); // swap the pointers,not the string data
  7. swap(lhs.i,rhs.i); // swap the int members
  8.  
  9. std::cout <<"swapping!\n";
  10. }
  11.  
  12. //! operator = using specific swap
  13. HasPtr&
  14. HasPtr::operator = (HasPtr rhs)
  15. {
  16. swap(*this,rhs);
  17. return *this;
  18. }

我的问题是为什么这样做效率不高?

解决方法

步骤1

设置执行移动赋值运算符的性能测试.

设置另一个执行复制赋值运算符的性能测试.

第2步

按照问题陈述中的指示,以两种方式设置赋值运算符.

第3步

迭代步骤1和2,直到您确信已正确执行它们.

第3步应该可以帮助您了解正在发生的事情,最有可能的方法是告诉您性能在哪里发生变化以及变化的位置.

猜测不是步骤1-3的选项.你实际上必须这样做.否则你(正确地)不相信你的猜测是正确的.

第4步

现在你可以开始猜测了.有些人会称之为“形成一种假设”.说“猜测”的奇特方式.但至少现在它是受过教育的猜测.

我在回答这个问题时进行了这个练习,并注意到一个测试没有显着的性能差异,另一个测试的性能差异为6倍.这进一步促使我得出一个假设.完成这项工作后,如果您不确定您的假设,请使用您的代码,结果和后续问题更新您的问题.

澄清

有两个特殊的成员赋值运算符,通常具有签名:

  1. HasPtr& operator=(const HasPtr& rhs); // copy assignment operator
  2. HasPtr& operator=(HasPtr&& rhs); // move assignment operator

可以使用单个赋值运算符实现移动赋值和复制赋值,并使用所谓的复制/交换习惯用法

  1. HasPtr& operator=(HasPtr rhs);

此单个赋值运算符不能使用第一个集重载.

使用复制/交换习惯用法实现两个赋值运算符(复制和移动)或仅使用一个是否更好?这就是练习13.53所要求的.要回答,您必须尝试两种方式,并测量复制分配和移动分配.聪明,善意的人通过猜测而不是测试/测量来弄错.你选择了一个很好的练习来学习.

猜你在找的C&C++相关文章