次に例を示します。
#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 回の呼び出しと、関連するデストラクターへの呼び出しが必要になります。BigCount::next()
コピーの省略が許可されているため、コピー コンストラクターの 1 回の呼び出しに減らすことができますnewcounter
。
operator =
次のように宣言および定義されていた場合:
BigCounter &BigCounter::operator =(const BigCounter &b) {
BigCounter tmp(b);
swap(tmp);
return *this;
}
コピーの省略があっても、コピー コンストラクターを 2 回呼び出す必要がありました。1 つは構築newcounter
し、もう1 つは構築しtmp
ます。そして、コピーの省略がなければ、まだ 3 になります。そのoperator =
ため、代入演算子に「コピー アンド スワップ」イディオムを使用する場合、その引数がコピー コンストラクトの呼び出しを必要とするように宣言することが最適化になる可能性があります。引数を作成するためにコピー コンストラクターが呼び出されると、その呼び出しが省略される場合がありますが、ローカル変数を作成するために呼び出される場合は省略されない場合があります。