以下の文は、Bruce Eckel によるThe Positive Legacy of C++ and Javaからの、C++ での演算子のオーバーロードに関するものです。
C++ にはスタック割り当てとヒープ割り当ての両方があり、演算子をオーバーロードしてすべての状況を処理し、メモリ リークを引き起こさないようにする必要があります。確かに難しい。
演算子のオーバーロードがメモリ割り当てとどのように関係しているのかわかりません。それらがどのように相関しているかを誰か説明できますか?
以下の文は、Bruce Eckel によるThe Positive Legacy of C++ and Javaからの、C++ での演算子のオーバーロードに関するものです。
C++ にはスタック割り当てとヒープ割り当ての両方があり、演算子をオーバーロードしてすべての状況を処理し、メモリ リークを引き起こさないようにする必要があります。確かに難しい。
演算子のオーバーロードがメモリ割り当てとどのように関係しているのかわかりません。それらがどのように相関しているかを誰か説明できますか?
私はいくつかの可能な解釈を想像することができます:
まず、C ++ではnew
、delete
どちらも実際には演算子です。これらの演算子をオーバーロードしてオブジェクトにカスタム割り当て動作を提供することを選択した場合は、リークが発生しないように十分に注意する必要があります。
operator=
次に、オブジェクトの種類によっては、メモリ管理のバグを回避するためにオーバーロードする必要があります。たとえば、参照カウントスマートポインタオブジェクト(Boost shared_ptrなど)がある場合は、を実装operator=
する必要があり、正しく実装する必要があります。この壊れた例を考えてみましょう。
template <class T>
class RefCountedPtr {
public:
RefCountedPtr(T *data) : mData(data) { mData->incrRefCount(); }
~RefCountedPtr() { mData->decrRefCount(); }
RefCountedPtr<T>& operator=(const RefCountedPtr<T>& other) {
mData = other.mData;
return *this;
}
...
protected:
T *mData;
};
ここでの実装は、参照カウントをoperator=
管理しないために壊れています。また、参照カウントをデクリメントしないため、リークが発生します。また、参照カウントをインクリメントしないため、実際の参照がすべてなくなる前に、ポイントされているオブジェクトが削除される可能性があるため、メモリ障害が発生する可能性があります。mData
other.mData
mData
other.mData
クラスに対して独自の実装を明示的に宣言しない場合operator=
、コンパイラーは、ここに示されている実装と同じ動作を持つデフォルトの実装を提供することに注意してください。つまり、この特定のケースでは完全に壊れています。
したがって、記事にあるように、場合によっては演算子をオーバーロードする必要があり、すべての状況を正しく処理するように注意する必要があります。
編集:申し訳ありませんが、参照が本ではなくオンライン記事であることに気づきませんでした。記事全体を読んだ後でも、何が意図されているのかは明確ではありませんが、Eckelはおそらく上記の2番目のような状況を参照していたと思います。
new と delete は、実際には C++ の演算子であり、オーバーライドして独自のカスタマイズされたメモリ管理を提供できます。ここで例を見てみましょう。
演算子は関数です。糖衣構文を追加したからといって、記憶に注意する必要がないというわけではありません。他のメンバー/グローバル/フレンド機能と同じようにメモリを管理する必要があります。
これは、ラッパーポインタクラスを実装するときにをオーバーロードするときに特に重要です。
operator+
次に、またはをオーバーロードすることにより、文字列の連結が行われoperator+=
ます。詳細については、basic_string
テンプレートをご覧ください。