1

次のクラスを検討してください。

class Stats
{
    private:
    int arraySize; // size of array

    int * data; // pointer to data, an array of integers

    // default size of array in default constructor
    static const int DEFAULT_SIZE = 10;

    public:
    Stats() // default constructor
    {
        arraySize = DEFAULT_SIZE; // element count set to 10

        data = new int[DEFAULT_SIZE]; // array of integers
        srand((unsigned int) time(NULL)); // seeds rand() function

        // initializes integer array data with random values
        for (int i = 0; i < DEFAULT_SIZE; i++)
        {
            // data filled with value between 0 and 10
            data[i] = rand() % (DEFAULT_SIZE + 1);
        }
    }

    ~Stats() // destructor that deletes data memory allocation
    {
        delete [] data;
    }

    void displaySampleSet(int numbersPerLine)
    {
        cout << "Array contents:" << endl; // user legibility

        // iterates through array and prints values in array data
        for (int i = 0; i < arraySize; i++)
        {
            cout << data[i];

            /*  nested if statements that either prints a comma between
            values or skips to next line depending on value of numbersPerLine   */
            if (i + 1 < arraySize)
            {
                if ((i + 1) % numbersPerLine != 0)
                    cout << ", ";
                else
                    cout << endl;
            }
        }
    }
}

何らかの理由で、次の方法で Stats オブジェクトを作成すると:

Stats statObject = Stats();

それから displaySampleSet() を呼び出すと、数値が正常に表示されます。ただし、Stats オブジェクトが次の方法で作成されると、関数はガベージを出力します。

Stats statObject;
statObject = Stats();

なぜこれを行うのかわかりませんし、整数ポインター「データ」および/またはオブジェクトの作成方法に関係していると感じていますが、何がわかりません...すべてのヘルプが完全です感謝!よろしくお願いします。

更新: デストラクタが追加されました

4

2 に答える 2

2

どちらのコード ステートメントも未定義の動作を生成します。最初のものは機能しますが、2番目のものは機能しません。

Stats statObject = Stats();

コピーの初期化です。既定のコンストラクターを呼び出して作成されたStatsオブジェクトをコピーしstatObject、コピー コンストラクターを呼び出してにコピーします。クラスはコピー コンストラクターを提供しないため、暗黙的に生成されたコンストラクターが使用されることに注意してください。これにより、動的に割り当てられたメンバーの浅いコピーが作成されます。このコピーの作成元のオブジェクトは最終的に破棄され、クラスに残っているのは、有効なものを指していないダングリング ポインターです。コピー コンストラクターは、ディープ コピーを実行する必要があります。

以下の場合も同様です。

Stats statObject;
statObject = Stats();

コンパイラが生成したコピー代入演算子が呼び出されます。ケース1と同様の問題が発生します。

3 つのルールに従い、コピー コンストラクターとコピー代入演算子をクラスに提供する必要があります。

于 2013-04-14T11:06:01.310 に答える
1

コードは、コンパイラによって定義された合成コピー コンストラクター、代入演算子を使用しています。また、デフォルトのコンストラクターに動的に割り当てられたメモリを解放していません。独自のコピー コンストラクター、オーバーロード代入演算子を定義する必要があります (3 つのルールに従います)。

どちらの場合も未定義の動作です

Stats statObject;
statObject = Stats();  //using compiler defined assignment operator.

Stats statObject = Stats();  //using compiler defined copy constructor.

ここで生成された一時オブジェクトは、コンパイラによってオーバーロードされた代入演算子を使用しており、ディープ コピーではなくシャロー コピーを実行しています。オーバーロード代入演算子:

Stats& operator=(const Stats& rhs);

コピー コンストラクターを定義します。

Stats(const Stats& rhs);
于 2013-04-14T11:14:43.067 に答える