0

私は、推奨される C++ の本の 1 つを読んでいました。

オブジェクトがそれ自体に割り当てられている場合でも、割り当て演算子が正しく機能することが非常に重要です。これを行う良い方法は、左側のオペランドを破棄する前に右側のオペランドをコピーすることです。

本の例; クラスには 1 つのデータ メンバーがpsあり、ps is string *

C& operator=(const C &rhs)
{
     auto newp = new string(*rhs.ps)
     delete ps;
     ps = newp;
     return *this;        
}

しかし、私たちのインストラクターは提案しました

C& operator=(const C &rhs)
{
    if (this == &rhs)
        return *this;

     delete ps;
     ps = new string(*rhs.ps)
     return *this;  
}

講師の対応に問題はないか

4

6 に答える 6

2

このアプローチに問題はありますか?

問題は、提案が示すことを実行しないことであり、いずれにせよそうあるべきです

C& operator=( const C &rhs)
{
    if ( this == &rhs)
        return *this;

    // ...
}

おそらく最終的な目的は、次のようなものを書くことです。

C& operator=( C temp)
{
  Swap( temp );
  return *this;
}

このトピックの詳細については、 copy swap idiomを参照し、「Exceptional C++」を参照してください。

于 2014-08-03T18:48:33.393 に答える
2

あなたのインストラクターのアプローチには欠陥があります。new string(*rhs.ps)失敗すると、例外がスローされps、無効な値が残ります (psは削除されたメモリへのポインターになります)。

new古いデータを削除する前に、 が成功したことを確認する必要があります。

C& operator=(const C &rhs)
{
     auto new_ps = new string(*rhs.ps);
     delete ps;
     ps = new_ps;
     return *this;  
}

必要に応じて自己代入を防ぐことができますが、それは必要ありません。また、自己代入は一般的なケースではないため、これを行うとプログラムのパフォーマンスが低下する可能性があります。

カスタム コピー代入演算子がある場合は、おそらくカスタム ムーブ代入演算子、コピー コンストラクター、ムーブ コンストラクター、およびデストラクターも必要になることに注意してください。(ルール・オブ・ファイブを参照)。

全体として、これはまだ欠陥のある設計です。psだけにするか、 value_ptrstringなどのスマート ポインターにする必要があります。メモリを手動で管理するのは面倒で、エラーが発生しやすくなります。

于 2014-08-03T19:40:26.277 に答える
2

次のパラダイムを使用して、最初に以前に割り当てられたリソースの割り当てを解除し、次に入力引数の属性に従ってそれらを再割り当てするケースを回避できます (そうしないと、入力引数リソースの割り当てが解除されるという望ましくないシナリオが発生します)。

C& operator=(const C &rhs)
{
    if (this == &rhs)
        return *this;

    // For example:
    delete[] m_arr;
    m_len = rhs.m_len;
    m_arr = new int[m_len];
    for (int i=0; i<m_len; i++)
        m_arr[i] = rhs.m_arr[i];
}
于 2014-08-03T18:42:39.863 に答える
2

コードがコンパイルされないという問題があります。それ以外の

if (this == rhs.this)

がなければならない

if (this == &rhs)

それ以外は問題ありません。

于 2014-08-03T18:42:51.703 に答える
-1

いいえ、そのアプローチに問題はありません。

さて、編集したところで問題が発生しました。良いアドバイスが必要な場合は、人々に完全な情報を提供することをお勧めします。

于 2014-08-03T18:36:06.967 に答える