0

私たちの教授は、カスタムの「文字列」テンプレート ファイルをオンラインで投稿し、しばらく前に以下の関数に記入するように依頼しました。これを理解しようとする私の質問は、なぜトップ 3 のコンストラクターがText = NULL;それの下にthis = source;あるのかということです。それぞれが言うべきだと思いますText = the_input_parameter

どうもありがとう、コードは次のとおりです。

class String
{
public:
    // Default constructor
    String()
    {
        Text = NULL;
    }
    String(const String& source)
    {
        Text = NULL;
        // Call the assignment operator to perform deep copy
        *this = source;     
    }
    String(const char* text)
    {
        Text = NULL;
        // Call the assignment operator to perform deep copy

        *this = text;

    }
~String()
    {
        delete[] Text;
    }

    // Assignment operator to perform deep copy
    String& operator = (const char* text)
    {
        // Ddispose of old Text
        delete[] Text;

        // +1 accounts for NULL-terminator
        int trueLength = GetLength(text) + 1;

        // Dynamically allocate characters on heap
        Text = new char[trueLength];

        // Copy all characters from source to Text; +1 accounts for NULL-terminator
        for ( int i = 0; i < trueLength; i++ )
            Text[i] = text[i];

        return *this;
    }

    // Returns a reference to a single character from this String
    char& operator [] (int index) const
    {
        int length = GetLength();

        // Check for valid index
        if ( (index < 0) || (index > length) )
        {
            stringstream error;
            error << "operator[] - index " << index << " is out of bounds (0.." << (length - 1) << ")";
            throw String(error.str().c_str());
        }

        return Text[index];
    }
private:
    // The encapsulated C-string
    char* Text;
};
4

3 に答える 3

6

代入に関してコンストラクターを実装すべきではない理由:

  • 派生クラスではかなり厄介です。考えてみてください。
  • 例外を安全にすることは困難です。
  • また、起動するのも非効率的です(デフォルトの構築と割り当てが必要です)。

したがって、コード例でそのように行われる理由に対する答えは、おそらく教授が C++ プログラミングについてあまり知らないということです。

そうでなければ、言うのは難しいです。それを行うのはまったく意味がありません。


ただし、別の方法、つまり、コピー構築の観点からコピー割り当てを実装することは非常に一般的であり、コピー アンド スワップ イディオムとして知られています。

シンプルで、例外に対して安全で、一般的に効率的で、次のようになります。

class Foo
{
public:
    void swap_with( Foo& other ) throw()
    {
        // No-throwing swap here.
    }

    void operator=( Foo other )
    {
        other.swap_with( *this );
    }
};

うん、それだけです。

バリアントには、スワッパーに just という名前を付けswapたり、代入演算子に参照を返させたりすることが含まれます。また、参照によって引数を渡してからコピーを作成することを好む人もいます (コピー構築を使用)。

于 2013-03-13T20:28:26.247 に答える
1

これは、一般的なコードをヘルパー関数に分解する方法にすぎません。この場合、operator=()ヘルパー関数として機能します。その機能は、現在の文字列 (この場合はNULL) の割り当てを解除し、右側のディープ コピーを実行することです。

それぞれが言うべきだと思いますText = the_input_parameter

正しい型ではないためString(const String& source)、これはコンパイルされません。source

これはString(const char* text)、ディープ コピーを実行する代わりにポインタを割り当てるだけなので、正しくありません。

上記は、クラスの一部のみを示していること、および実際のクラスが適切な代入演算子とデストラクタを定義していることを前提としています。そうでない場合は、新しい教授が必要です。

于 2013-03-13T20:17:44.983 に答える