0

私は現在、ファイルから球体を読み取ることになっている割り当てに座っています。ファイルからの一般的な入力は次のようになります: "0.182361 -0.0170570.1295820.001816"。、x、y、z座標と球の半径を表します。ファイルを読んでいる間、私は自分の方法を使用しています:「AddSphere」は球を配列に追加します。

void Array::AddSphere(MySphere inp)
{
if (length == 10000 || length == 200000 || length == 30000)
{
    ResizeBuffer(); 
}
this->length++;
*arr = inp;
arr++;
//this->length++;
}

クラス「Array」は、すべての球のホルダーのようなものであり、現在の要素を指している変数「arr」を含んでいます。

    class Array
    {
    public :

    int length;
    void AddSphere(MySphere inp);
    int arrLength();
    void RemoveAt(int pos);
    void AddFromFile();
    MySphere * Buffer;
    void CreatenewBuffer();
    private:
    MySphere * arr;

    public:Array()
       {
           Buffer = new MySphere[10000];
           arr = Buffer;
           length = 0;
       }
       ~Array()
       {
           delete[] arr;
           delete[] Buffer;
       }
};

また、「arr」の最初の要素を指している「Buffer」も含まれています。だから今私の問題は何ですか?問題は、「長さ」が指定された値に等しいときはいつでも、バッファのサイズを動的に増やすことができるようにしたいということです。私のファイルに15000個の要素が含まれているとしましょう。次に、配列に正しい長さを持たせるために、バッファサイズを増やす必要があります。ResizeBuffer()を使用して、それを実行しようとします。

    void Array::ResizeBuffer()
{

    MySphere * tempBuff = new MySphere[length+10000];
    memcpy(tempBuff, Buffer, sizeof((MySphere)*Buffer));
    this->Buffer = new MySphere[length+10000];
    arr = Buffer;
    memcpy(Buffer, tempBuff, sizeof((MySphere)*tempBuff));


    //int a = 0;

    }

しかし、何らかの理由で、15000のすべてではなく、出力の最後の5000の要素しか取得しません。これは、arrのポインターがバッファー全体を指していないことと関係があると考えましたが、どの試みも機能しません。では、なぜこれが起こっているのでしょうか?

お時間をいただきありがとうございます!

4

4 に答える 4

3

いくつかの問題:

動的データは1回だけ割り当てられます(ただし、領域へのポインターは2つあります)。

Array()
   {
       Buffer = new MySphere[10000];
       arr = Buffer;
       length = 0;
   }

したがって、削除できるのは1回だけです(1つの割り当てと1つの破棄)。

   ~Array()
   {
       delete[] arr;
       delete[] Buffer;  // Double delete.
   }

オブジェクトをコピーする場合、memcpyを使用することはできません(オブジェクトが非常に特別なサブカテゴリに分類されない限り)。メソッドと他のすべての機能でC++を使用する場合、これが当てはまる可能性はほとんどありません。std :: copy()を使用して、ある配列から別の配列にコンテンツをコピーすることをお勧めします。

MySphere * tempBuff = new MySphere[length+10000];
memcpy(tempBuff, Buffer, sizeof((MySphere)*Buffer));
this->Buffer = new MySphere[length+10000];
arr = Buffer;
memcpy(Buffer, tempBuff, sizeof((MySphere)*tempBuff));

また、なぜそれを2回コピーするのですか?

std :: copy
の使用に加えて、サイズ変更は3つの異なるフェーズで行われる必要があることに注意してください。

1. Allocate and copy data       // Dangerous may throw
2. Reset object                 // Safe
3. Release old resources.       // Dangerous may throw

だから、これはそれがどのように見えるべきかです。

// Phase 1: Allocate and copy.
std::unique_ptr<MySphere> tempBuffer = new MySphere[length+1000];   // Hold in a smart pointer
                                                                    // For exception safety
// Prefer to use std::copy. It will use the objects copy constructor
std::copy(Buffer, Buffer+length, MySphere);                         // Copies the objects correctly. 


// Everything worked so Phase 2. Reset the state of the object.
// We can now put the tempBuffer into the object
MySphere* toDelete = Buffer;                                        // keep old buffer for stage 3.
Buffer = tempBuffer.release();
length += 1000;

// Phase 3
// State of the new object is consistent.
// We can now delete the old array
delete [] toDelete;

スマートポインタの使用が許可されていない場合。次に、フェーズ1を次のように置き換えます。

// Phase 1: Allocate and copy.
MySphere* tempBuffer = new MySphere[length+1000];

try                                                 // For exception safety
{
    // Prefer to use std::copy. It will use the objects copy constructor
    std::copy(Buffer, Buffer+length, MySphere);     // Copies the objects correctly. 
}
catch(...)
{
    delete [] tempBuffer;
    throw;
}

クラスが動的に割り当てられたオブジェクトの所有権を取得したため。クラスも三つのルールを実装する必要があります。これは、コピーコンストラクタと代入演算子を定義する必要があることを意味します。

動的配列が本当に必要なのは、次の3つです。

    1) A pointer to the buffer.
    2) The current size the user knows about (reported by size)
    3) The actual size. At which point you need to resize

配列に三つのルールを実装する方法の例を次に示します。

https://stackoverflow.com/a/255744/14065

それ以外は不要です。

これはプロジェクトであるため、あなたの場合は不要です。ただし、追加のマークについては、新しい配置の使用方法を調べてください。これにより、配列に実際には存在しないオブジェクトの余分な初期化を防ぐことができます。

新しい場所の使用方法の例:

https://stackoverflow.com/a/13994853/14065

于 2013-01-28T16:44:45.963 に答える
1

Array :: CreatenewBuffer()関数内で長さ変数を更新していません。

オブジェクトを反復処理している場所は、おそらく次のようなものだと思います...

for (size_t i = 0; i < Array.length; ++i)
    printf("Item found");

振り返ってみると、長さの使い方は実際にはかなり混乱しています。サイズと容量の2つの変数に分割することをお勧めします。容量は、現在割り当てられているバッファーが保持できるオブジェクトの量であり、サイズは、実際にバッファーに追加されたオブジェクトの量です。

于 2013-01-28T16:43:48.633 に答える
1

これはどう?

void Array::CreatenewBuffer()
{
    MySphere * tempBuff = new MySphere[length+10000];
    std::copy ( Buffer, Buffer+length, tempBuff );
    delete[]Buffer;
    Buffer = tempBuff;
    delete[]tempBuff;
}
于 2013-01-28T17:37:00.313 に答える
0

各球の値は別々の行に入力されていますか?もしそうなら、あなたは単に行を数え、それから正しい値でバッファを初期化することができます。

于 2013-01-28T16:44:49.287 に答える