web-dev-qa-db-ja.com

コンストラクター初期化子で配列サイズを決定する

以下のコードでは、Classコンストラクターが呼び出されたときに、配列がサイズxの配列として定義されるようにしています。どうやってやるの?

class Class
{
public:
  int array[];
  Class(int x) : ??? { }
}
17
zaratustra

コンパイル時に計算できない非const次元の配列のサイズを初期化することはできません(少なくとも、現在のC++標準のAFAIKでは)。

配列の代わりにstd::vector<int>を使用することをお勧めします。ほとんどの操作に配列のような構文を提供します。

21

皆さんはこれを非常に複雑にしています。もちろん、C++でこれを行うことができます。効率を上げるために、通常の配列を使用しても問題ありません。ベクトルは、配列の最終的なサイズが事前にわからない場合、つまり、時間とともに拡大する必要がある場合にのみ意味があります。

チェーンの1レベル上の配列サイズがわかっている場合は、動的割り当てもメモリリークの可能性もないため、テンプレートクラスが最も簡単です。

template < int ARRAY_LEN > // you can even set to a default value here of C++'11

class MyClass
  {   
  int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure!  Works like you imagine!   
  }

// Then you set the length of each object where you declare the object, e.g.

MyClass<1024> instance; // But only works for constant values, i.e. known to compiler

オブジェクトを宣言する場所で長さがわからない場合、または同じオブジェクトを異なる長さで再利用する場合、または不明な長さを受け入れる必要がある場合は、コンストラクターに割り当てて解放する必要があります。あなたのデストラクタ...(そして理論的には常にそれが機能したことを確認してください...)

class MyClass
  {
  int *array;

  MyClass(int len) { array = calloc(sizeof(int), len); assert(array); }   
  ~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE!
  }
52
Jeff Diamond

新しい演算子を使用します。

class Class
{
   int* array;
   Class(int x) : array(new int[x]) {};
};
14
John Dibling

それができるとは思いません。少なくともあなたが望む方法ではありません。サイズが動的情報(x)に由来する場合、静的サイズの配列(array [])を作成することはできません。

ポインターへのポインターとサイズを保存し、コピーコンストラクター、代入演算子、デストラクターをオーバーロードして処理するか、std :: vectorを使用する必要があります。

class Class
{
  ::std::vector<int> array;
  Class(int x) : array(x) { }
};
4
AFoglia

この古いスレッドを壊してごめんなさい。実際には、配列のコンパイル時のサイズを調べる方法があります。それはこのようなものになります:

#include <cstdlib>

template<typename T>
    class Class
    {
        T* _Buffer;

        public:
        template<size_t SIZE>
            Class(T (&static_array)[SIZE])
            {
                _Buffer = (T*)malloc(sizeof(T) * SIZE);

                memcpy(_Buffer, static_array, sizeof(T) * SIZE);
            }

            ~Class()
            {
                if(_Buffer)
                {
                    free(_Buffer);
                    _Buffer = NULL;
                }
            }
    };

int main()
{
    int int_array[32];
    Class<int> c = Class<int>(int_array);

    return 0;
}

または、malloc/newが嫌いな場合は、代わりにサイズテンプレートクラスを作成できます。しかし、私はそれを本当にお勧めしませんし、構文は非常に醜いです。

#include <cstdio>

template<typename T, size_t SIZE>
    class Class
    {
        private:
            T _Array[sz];
        public:
            Class(T (&static_array)[SIZE])
            {
                memcpy(_Array, static_array, sizeof(T) * SIZE);
            }
    };

int main()
{
    char int_array[32];
    Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array);
    return 0;
}

とにかく、これがお役に立てば幸いです:)

3
user563910

ベクトルを使用する必要がないことを理解していません。配列を使用したい場合、効率の問題です。スペースが少ない、コピー時間が発生しない(このような場合、適切に処理されれば、デストラクタ内で配列を削除する必要すらありません)など、理由にかかわらず。

正解は:(引用)

class Class
{
   int* array;
   Class(int x) : array(new int[x]) {};
};

最適でない代替手段を強制的に使用させようとしないでください。そうしないと、経験の浅いプログラマーを混乱させてしまいます。

生の配列を使用する代わりに、ベクターを使用してみませんか。

class SomeType {
  vector<int> v;
  SomeType(size_t x): v(x) {}
};

ベクトルを使用すると、例外に直面した場合の自動リーク保護と、ローアレイに比べて他の多くの利点が得られます。

1
JaredPar

C++ではできません-代わりにstd :: vectorを使用してください:

#include <vector>

struct A {
   std::vector <int> vec; 
   A( int size ) : vec( size ) {
   }
};
0
anon

配列をポインタとして宣言します。イニシャライザリストで後でnewを使用して初期化できます。

未知のサイズのベクトルを使用する方が良い。

可変長配列についても この質問 を確認することをお勧めします。

0
Shree

私は同じ問題を抱えていて、このように解決しました

class example
{
  int *array;

  example (int size)
  {
    array = new int[size];
  }
}
0
Sherazi Rajput

2つのオプション:

Std :: vectorを使用します。これにより、アレイのサイズを簡単に変更できます。
std :: tr1 :: arrayを使用します。これには静的なサイズがあります。

どちらもコンストラクタ初期化子リストで正しく初期化できます。

0
Martin York