プレフィックス/ポストフィックス増分演算子
-
02-10-2019 - |
質問
パスバイバージとパスバイレファレンスを適切に理解していることを確認したいと思っています。特に、増分のプレフィックス/ポストフィックスバージョンを見ています ++
オブジェクトのオペレーター。
次のクラスがあるとしましょう X
:
class X{
private:
int i;
public:
X(){i=0;}
X& operator ++ (){ ++i; return *this; } //prefix increment
X operator ++ (int unused){ //postfix increment
X ret(*this);
i++;
return ret;
}
operator int(){ return i; } //int cast
};
まず、プレフィックス/ポストフィックス増分演算子を適切に実装しましたか?
第二に、プレフィックス演算子と比較して、ポストフィックス演算子はどの程度メモリ効率が高いのでしょうか?具体的にはいくつ X
オブジェクトコピーは、オペレーターの各バージョンが使用されるときに作成されますか?
返品ごとに何が起こるかについて正確に何が起こるかについての説明は、私が理解するのに役立つかもしれません。
編集:たとえば、次のコードで...
X a;
X b=a++;
... AとBは今エイリアスですか?
解決
これは正しい実装です。インクリメントを行う前に別のコピーを作成する必要があるため、ポストフィックスオペレーターがパフォーマンスで悪化することが典型的です(これが、何か他のものが必要な場合を除き、常にプレフィックスを使用する習慣に身を任せた理由です)。
返品ごとに、現在のオブジェクトへのL値の参照を返します。コンパイラは通常、現在のオブジェクトのアドレスを返すことにより、これを実装します。これは、オブジェクトを返すことは、数字を返すのと同じくらい簡単であることを意味します。
ただし、返品ごとにコピーを実行する必要があります。これは、返品中に(住所のみではなく)コピーするためのより多くの情報と、コピーコンストラクターが呼び出すことを意味します。これがあなたのパフォーマンスのヒットが来るところです。
実装の効率は、一般的な実装では標準に見えます。
編集:補遺に関しては、いや、エイリアスではありません。 2つの別々のオブジェクトを作成しました。値で戻るとき(そして、ポストフィックスインクリメント演算子内から新しいオブジェクトを作成したとき)、この新しいオブジェクトは別々のメモリ位置に配置されます。
ただし、次のコードでは、AとB それは エイリアス:
int a = 0;
int& b = ++a;
Bは、aを参照するアドレスです。
他のヒント
接頭辞の増分を呼び出す方が慣用的です オブジェクト自体の ポストフィックスの増加:
X operator++(int)
{
X copy(*this);
++*this; // call the prefix increment
return copy;
}
インクリメントのロジック X
したがって、オブジェクトはプレフィックスバージョン内にのみ含まれています。
オペレーターは正しく実装されています。
プレフィックス演算子では、xのコピーは作成されていません。
Postfixオペレーターでは、1つのコピーがret用に作成され、 潜在的に 関数から戻るときに別のコピーが作成されますが、すべてのコンパイラがこのコピーを削除します。