Определить размер массива в инициализаторе конструктора - PullRequest
14 голосов
/ 15 апреля 2009

В приведенном ниже коде я хотел бы, чтобы массив определялся как массив размера x при вызове конструктора Class. Как я могу это сделать?

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

Ответы [ 11 ]

44 голосов
/ 05 сентября 2012

Вы, ребята, слишком усложнили это. Конечно, вы можете сделать это в C ++. Для него вполне нормально использовать обычный массив для эффективности. Вектор имеет смысл только в том случае, если он заранее не знает окончательный размер массива, т. Е. Он должен расти со временем.

Если вы знаете размер массива на один уровень выше в цепочке, шаблонный класс самый простой, потому что нет динамического выделения и нет шансов утечки памяти:

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!
  }
20 голосов
/ 15 апреля 2009

Вы не можете инициализировать размер массива с неконстантным измерением, которое не может быть вычислено во время компиляции (по крайней мере, в текущем стандарте C ++, AFAIK).

Я рекомендую использовать std::vector<int> вместо массива. Он предоставляет синтаксис, похожий на массив, для большинства операций.

11 голосов
/ 15 апреля 2009

Используйте новый оператор:

class Class
{
   int* array;
   Class(int x) : array(new int[x]) {};
};
4 голосов
/ 06 декабря 2010

Разве вы не понимаете, что нет необходимости использовать vector, если кто-то хочет использовать массивы, это вопрос эффективности, например. меньше места, нет времени на копирование (в этом случае, если обрабатывается должным образом, нет необходимости даже удалять массив внутри деструктора) и т. д. по любой причине.

правильный ответ: (цитируется)

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

Не пытайтесь заставить кого-то использовать неоптимальные альтернативы, иначе вы запутаете неопытных программистов

4 голосов
/ 15 апреля 2009

Не думаю, что это можно сделать. По крайней мере, не так, как вы хотите. Вы не можете создать массив статического размера (array []), если размер основан на динамической информации (x).

Вам нужно либо сохранить указатель на int и размер, и перегрузить конструктор копирования, оператор присваивания и деструктор для его обработки, либо использовать std :: vector.

class Class
{
  ::std::vector<int> array;
  Class(int x) : array(x) { }
};
3 голосов
/ 06 января 2011

Извините за некрозу этой старой темы. На самом деле есть способ узнать размер массива во время компиляции. Это выглядит примерно так:

#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;
}

В любом случае, я надеюсь, что это было полезно:)

1 голос
/ 15 апреля 2009

Вместо использования необработанного массива, почему бы не использовать вектор вместо.

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

Использование вектора предоставит вам автоматическую защиту от утечек перед лицом исключения и многие другие преимущества по сравнению с необработанным массивом.

0 голосов
/ 13 октября 2018

У меня была такая же проблема, и я решил ее таким образом

class example
{
  int *array;

  example (int size)
  {
    array = new int[size];
  }
}
0 голосов
/ 15 апреля 2009

Два варианта:

Используйте std :: vector. Это позволяет легко изменить размер массива.
Используйте std :: tr1 :: array. Это имеет статический размер.

Оба могут быть правильно инициализированы в списке инициализатора конструкторов.

0 голосов
/ 15 апреля 2009

Объявите ваш массив как указатель. Вы можете инициализировать его в списке инициализаторов позже через new.

Лучше использовать вектор для неизвестного размера.

Возможно, вы захотите взглянуть на этот вопрос и на массивы переменной длины.

...