【发布时间】:2014-01-27 10:08:20
【问题描述】:
这是C++ Primer 5th Edition中的一个练习:
练习 13.53: 作为低级效率问题,HasPtr 赋值运算符并不理想。解释为什么。实施一个 HasPtr 的复制赋值和移动赋值运算符并进行比较 在新的移动赋值运算符中执行的操作与 复制和交换版本。(P.544)
文件hasptr.h:
//! a class holding a std::string*
class HasPtr
{
friend void swap(HasPtr&, HasPtr&);
friend bool operator <(const HasPtr& lhs, const HasPtr& rhs);
public:
//! default constructor.
HasPtr(const std::string &s = std::string()):
ps(new std::string(s)), i(0)
{ }
//! copy constructor.
HasPtr(const HasPtr& hp) :
ps(new std::string(*hp.ps)), i(hp.i)
{ }
//! move constructor.
HasPtr(HasPtr&& hp) noexcept :
ps(hp.ps), i(hp.i)
{ hp.ps = nullptr; }
//! assignment operator
HasPtr&
operator = (HasPtr rhs);
//! destructor.
~HasPtr()
{
delete ps;
}
private:
std::string *ps;
int i;
};
部分文件hasptr.cpp:
//! specific swap.
inline void
swap(HasPtr &lhs, HasPtr &rhs)
{
using std::swap;
swap(lhs.ps, rhs.ps); // swap the pointers, not the string data
swap(lhs.i, rhs.i); // swap the int members
std::cout <<"swapping!\n";
}
//! operator = using specific swap
HasPtr&
HasPtr::operator = (HasPtr rhs)
{
swap(*this,rhs);
return *this;
}
我的问题是为什么这样做效率不高?
【问题讨论】:
-
为了回答这个问题,你首先要实现复制和移动。然后使用它们。然后比较发生了什么操作 - 计算移动和复制分配调用了多少移动和复制构造函数,以及上面的那个。
-
@Yakk '你首先必须实现复制和移动'--你的意思是复制和移动分配?
-
因为它复制了它?
-
另一个不同的问题是你为什么要维护一个指向
std::string的指针,答案是在99%的情况下你不想这样做.但回到最初的问题,给 lvalue 分配一个长度相同或更小的字符串会有什么影响? -
@Alan.W:没有理由(在大多数情况下)动态创建
std::string,它的代价是额外的内存分配和必须管理生命周期的痛苦。鉴于没有优点和一些缺点,我会避免这样做(我在生产代码中从未遇到过,在代码审查中我不会接受)
标签: c++ c++11 move-semantics assignment-operator rvalue-reference