这是一个例子:
#include <vector>
#include <climits>
class BigCounter {
public:
BigCounter &operator =(BigCounter b) {
swap(b);
return *this;
}
BigCounter next() const;
void swap(BigCounter &b) {
vals_.swap(b);
}
private:
typedef ::std::vector<unsigned int> valvec_t;
valvec_t vals_;
};
BigCounter BigCounter::next() const
{
BigCounter newcounter(*this);
unsigned int carry = 1;
for (valvec_t::iterator i = newcounter.vals_.begin();
carry > 0 && i != newcounter.vals_.end();
++i)
{
if (*i <= (UINT_MAX - carry)) {
*i += carry;
} else {
*i += carry;
carry = 1;
}
}
if (carry > 0) {
newcounter.vals_.push_back(carry);
}
return newcounter;
}
void someFunction()
{
BigCounter loopcount;
while (true) {
loopcount = loopcount.next();
}
}
somefunction
在行中loopcount = loopcount.next();
从复制省略中受益匪浅。如果不允许复制省略,则该行将需要复制构造函数的 3 次调用以及对析构函数的关联调用。在允许复制省略的情况下,它可以减少到复制构造函数的 1 次调用,在BigCount::next()
wherenewcounter
中显式地声明了一次。
如果operator =
已像这样声明和定义:
BigCounter &BigCounter::operator =(const BigCounter &b) {
BigCounter tmp(b);
swap(tmp);
return *this;
}
即使使用复制省略,也必须调用 2 次复制构造函数。一个构建newcounter
,另一个构建tmp
。如果没有复制省略,仍然会是 3。这就是为什么声明operator =
它的参数需要调用复制构造在使用赋值运算符的“复制和交换”习惯用法时可以是一种优化。当复制构造函数被调用来构造一个参数时,它的调用可能会被省略,但如果它被调用来创建一个局部变量,它可能不会。