1

オブジェクトがどのように渡されるか(参照または値)およびオブジェクトが配列にどのように格納されるかについての情報が見つからないため、C++でオブジェクトの配列を処理することについて少し混乱しています。

オブジェクトの配列はそのオブジェクトタイプへのポインタの配列であると思いますが、これがどこにも書かれているのは見つかりませんでした。それらはポインタでしょうか、それともオブジェクト自体がメモリ内の配列に配置されているのでしょうか。

以下の例では、カスタムクラスmyClassが文字列を保持します(これにより可変サイズになりますか、または文字列オブジェクトが文字列へのポインタを保持するため、一定量のスペースを占有します。 myContainer内のmyClassオブジェクト。myContainer.addObject()メソッドで、より大きな配列を作成し、すべてのオブジェクトを新しいオブジェクトと一緒にその配列にコピーしてから、古いオブジェクトを削除しようとしています。 mデストラクタを使用してメモリを適切にクリーンアップします-この領域でどのような改善を行うことができますか?

class myClass
{
    private:
          string myName;
          unsigned short myAmount;

    public:
        myClass(string name, unsigned short amount)
        {
            myName = name;
        myAmount = amount;
        }

    //Do I need a destructor here? I don't think so because I don't do any
    // dynamic memory allocation within this class
};



class myContainer
{
    int numObjects;
    myClass * myObjects;

   public:
    myContainer()
    {
        numObjects = 0;
    }   

    ~myContainer()
    {
        //Is this sufficient?
        //Or do I need to iterate through myObjects and delete each
        // individually?
        delete [] myObjects;
    }


    void addObject(string name, unsigned short amount)
    {
        myClass newObject = new myClass(name, amount);

        myClass * tempObjects;
        tempObjects = new myClass[numObjects+1];
        for (int i=0; i<numObjects; i++)
            tempObjects[i] = myObjects[i]);
        tempObjects[numObjects] = newObject;
        numObjects++;
        delete newObject;

        //Will this delete all my objects? I think it won't.
        //I'm just trying to delete the old array, and have the new array hold
        // all the objects plus the new object.
        delete [] myObjects;
        myObjects = tempObjects;
    }
};
4

4 に答える 4

3

いいえ、動的配列はその型へのポインターの配列ではありません-最初の要素へのポインターです。要素はメモリ内に連続して配置され、配列がdelete[]編集されると破棄されます。

したがって、割り当て解除は問題なく表示されます。オブジェクトの動的配列を作成するため、個別にmyClassオブジェクトを作成する必要はありません。deleteこれを行う必要があるのは、(動的に割り当てられた)オブジェクトへのポインターの配列がある場合のみです。

ただし、2つの決定的なエラーがあります。

tempObjects[numObjects] = newObject; // assign a myClass pointer to a myClass instance?

これは例である必要があります:

tempObjects[numObjects] = myClass(name, amount);

また、myObjects初期化されることはありません。つまり、ガベージが含まれており、逆参照/使用すると未定義の動作が発生します。

最後に、学習目的でこれを行う場合を除いて、std::vectorすでにすべての作業を行っているようなコンテナーを使用するだけです。

于 2010-03-20T09:55:23.950 に答える
3

C ++の配列は、メモリに配置されたオブジェクトの配列です。たとえば、次のようになります。

struct pair {
   int x; int y;
};
...
pair array[10];

配列内の各アイテムのサイズは2intになります。ポインタの配列が必要な場合は、次のように宣言するだけです。

pair* array_of_pointers[10];

文字列オブジェクトには、文字列の可変サイズ部分へのポインタがあります。だから彼らは安全です。実際、これらはここでの重要な教訓です。文字列クラスを使用して過度のメモリ処理を回避するのと同じ方法で、ベクトルクラスを使用して動的配列を処理する際のすべての問題を回避できます。

演習としてこれを行っている場合。ここにいくつかの問題があります: newObjectを使わずにローカルに割り当てる必要がありますnew。これにより、コードが正しくなり(newObjectポインタではなく、ポインタをnew返すため)、メモリを明示的に処理する手間も省けます。(より高度な注意点として、これにより、もう1つの場所でコード例外が安全になります) myObjectは初期化されません。また、コンストラクターで初期化リストを使用しません。コンストラクターは次のようになります。

myContainer() : numObjects(0), myObjects(NULL)
{

}  

コード内のデストラクタは、本来あるべきものとまったく同じです。

于 2010-03-20T10:12:58.423 に答える
1

オブジェクトの配列はそのオブジェクトタイプへのポインタの配列であると思いますが、これがどこにも書かれているのは見つかりませんでした。それらはポインタでしょうか、それともオブジェクト自体がメモリ内の配列に配置されているのでしょうか。

配列はオブジェクト自体で構成されます。ポインタの配列が必要な場合は、次のことを宣言する必要があります。

myClass ** tempObjects;  
tempObjects = new myClass*[numObjects+1];  

私はあなたがC#またはJavaに慣れていると思いますか?これらの言語では、オブジェクトはヒープにのみ割り当てることができ、常に参照によってアクセスされます。C ++でも可能ですが、C ++では、オブジェクトを直接スタックに配置したり、オブジェクト自体の配列を直接構築したりすることもできます。

以下の例では、カスタムクラスmyClassが文字列を保持します(これにより可変サイズになりますか、それとも文字列オブジェクトが文字列へのポインタを保持するため、一定量のスペースを占有しますか?

2番目:文字列オブジェクト自体のサイズは一定ですが、ヒープから割り当てられた動的なサイズのバッファーへのポインターがあります。

割り当て解除は問題ないように見えると思います。コードはさまざまな方法でより効率的に記述できますが、正しく見えます。

于 2010-03-20T10:01:22.627 に答える
0

それをテストして、何が起こるかを確認してください(はい、コンパイラ固有の可能性がありますが、それでも)...カスタムデストラクタをmyClassに追加してみてください(必要ない場合でも)。呼び出されたときに「グローバル」カウンター、次に配列を削除した後にカウンターを出力します。

各オブジェクトのデストラクタが呼び出されることを期待します。継承されたオブジェクトを配列に入れることができるように(「スライス」を回避するために)、オブジェクトは「ポインタごと」に格納されることがよくあることに注意してください。

于 2010-03-20T09:55:32.187 に答える