0

オブジェクト Ball の 2 次元配列を格納する ParticleMatrix というクラスを作成しています。それらに動的にスペースを割り当てたい。コードは次のようになります。

/* 
 * allocateParticle takes a width w, height h, restlength RL then allocates space for
 * and constructs a 2D array of Particles of subclass Ball. 
 */ 
void ParticleMatrix::allocParticles(int w, int h, float RL)
{
    // Gets the number of particles in the xDirection
    xPart = getNrPart(w,RL);
    // Gets the number of particles in the yDirection
    yPart = getNrPart(h,RL);

    // Allocates a row of pointers to pointers.
    ballArray = new Ball*[xPart];
    // The ID of the particles.
    int ID = 0;

    // For every particle in the xDirection
    for(int x = 0; x<xPart; x++)
    {
        // Allocate a row of Ball-pointers yPart long.
        ballArray[x] = new Ball[yPart];

        // For every allocated space
        for(int y = 0; y<yPart; y++)
        {
            // Construct a Ball
            ballArray[x][y] = Ball( ID, RL*(float)x, RL*(float)y);
            ID++;
        }
    }
}

この問題は、「ballArray[x] = new Ball[yPart]」という行で発生します。CodeBlocks を実行すると、" error: no matching function for call to 'Ball::Ball()' " というコンパイラ エラーが表示されます。Ball には、異なる署名を持つ 4 つのコンストラクターがありますが、「Ball()」のようなものはありません。

コンストラクター「Ball::Ball()」を追加してみましたが、コンパイルされますが、オブジェクトにスペースを割り当てて後でインスタンス化できるはずだと感じています。

私が疑問に思っているのは、上記のコードにコンストラクター「Ball::Ball()」がないと、オブジェクト Ball にスペースを割り当てられないのはなぜですか? そして:コンストラクター「Ball::Ball()」なしで何らかの方法でスペースを割り当てることができる場合、どうすればそれを行うことができますか?

コンストラクター "Ball::Ball()" を作成し、オブジェクトにダミーの値を与えて、後で必要な値に設定できることはわかっていますが、単に "スペースの割り当て -> オブジェクトのインスタンス化". 私の問題を説明できたことを願っています。ありがとう!

4

3 に答える 3

1

これを行うもう 1 つの「C++ の方法」は、std::allocator.

要素を構築せずにメモリを予約するだけallocateです。deallocate

  std::allocator<Ball*> ball_ptr_allocator;
  std::allocator<Ball> ball_allocator;

  Ball ** ptr = ball_ptr_allocator.allocate(10);

  for (size_t x=0; x<10; ++x)
  {
    ptr[x] = ball_allocator.allocate(10);
    for (size_t y=0; y<10; ++y)
    {
      ball_allocator.construct(&ptr[x][y], ID, RL*(float)x, RL*(float)y);
      // if you do not have access to C++11 use this:
      // ball_allocator.construct(&ptr[x][y], Ball(ID, RL*(float)x, RL*(float)y));
      ++ID;
    }

ここでいくつかの問題に注意してください。

  • 通常、サイズには符号なしの型を使用することをお勧めします (たとえば、size_t など)。

  • アロケータをアクセスできるメンバーにすると、デストラクタなどにあり、再び割り当てを解除できます。std::allocator<Ball> m_ballAlloc;

  • 構築された要素と割り当てられたメモリを(どういうわけか)追跡する必要があります。構築の 1 つが例外をスローする場合、構築された要素をクリーンアップし、割り当てられたメモリの割り当てを解除できるはずです。

割り当て解除の追跡については、allocParticles に追加のループを使用できます。

for(size_t x = 0; x<xPart; x++) ballArray[x] = nullptr;

ballArray[i]これで、nullptr ではないものはすべて割り当てを解除する必要があることがわかりました。

ただし、最初に要素を破壊する必要があります。ID をクラスのメンバー変数にすると、それを使用して構築された要素を破棄できます (要素の構築後にのみインクリメントされるため)。

ballArray の破壊のみに関してデストラクタの例を書きましたが、他のリソースが存在する場合は、それも処理する必要があることに注意してください。

~ParticleMatrix (void)
{
    // check this here and set ballArray to nullptr upon construction
    // of the ParticleMatrix
    if (ballArray != nullptr)
    {
        // start to destroy the Balls
        size_t destroycounter(0U);
        for(size_t x = 0; x<xPart; x++)
        {
            for(size_t y = 0; y<yPart; y++)
            {
                if (destroycounter < ID) 
                {
                    m_ballAlloc.destroy(&ballArray[x][y]);
                    ++destroycounter;
                }
            }
        }
        // deallocate 2nd dimension arrays
        for(size_t x = 0; x<xPart; x++) 
        {
            if (ballArray[x] != nullptr) m_ballAlloc.deallocate(ballArray[x], yPart);
        }
        // deallocate first dimension
        delete [] ballArray;
    }
}
于 2013-06-22T13:32:09.713 に答える