2009-04-15 2 views
13

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

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

I Если вы планируете регулярно использовать C++, я настоятельно рекомендую вам ознакомиться со стандартной библиотекой шаблонов. Это упрощает работу с коллекциями данных. – Brian

+1

В качестве сторонних векторов относительно легко работать с массивом, не зная размера заранее. Нет необходимости знать размер заранее; вы можете добавлять элементы в конец вектора в (амортизированном) O (1) времени так или иначе, используя push_back. – Brian

+0

Использование векторов приносит новые проблемы, так как класс, который я пытаюсь использовать для векторизации, защитил «новых» операторов. Но это было не то, о чем я так не поверил. – zaratustra

ответ

17

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

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

+0

Каким будет синтаксис использования вектора в этой ситуации? – zaratustra

+2

vector < int > массив; Класс (x): array (x) {}; – DevSolar

1

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

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

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

+0

Вы имеете в виду «Использование * вектора * даст вам автоматическую защиту от утечек»? :) – mkb

+0

@mkb, это уже два раза, сегодня я сделал принципиально глупые комментарии. Должен выпить больше кофе, чтобы проснуться, прежде чем я начну размещать;) – JaredPar

11

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

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

Не забудьте вызвать delete [] в конструкторе, если вы используете этот код. – Brian

+7

Если вы это сделаете, вам также понадобится конструктор копирования, оператор присваивания и деструктор. Использование std :: vector дает вам точно такую ​​же функциональность, но не требует ни одного из них. – 2009-04-15 14:15:08

+0

+1 Это фактически отвечает на вопрос OP, инициализируя размер массива, хотя он фактически заменяет 'int * array', который не является массивом, со списком в конструкторе. @ (anon), помимо конструктора копирования, оператора присваивания и деструктора, это действительно отвечает на вопрос. –

0

Вы не можете сделать это в C++ - использовать зЬй :: вектор вместо:

#include <vector> 

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

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

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

Возможно, вы захотите посмотреть на this question также на массивы переменной длины.

+0

лучше использовать вектор для известного размера тоже – 2009-04-15 14:17:51

+0

должны согласиться с тем, что – Shree

+0

ПЛОХАЯ идея. Выполнение управления памятью на указателе, который действует как массив, не является тривиальным при наличии исключений. Используйте std :: vector или std :: tr1 :: array. –

3

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

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

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

два варианта:

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

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

4

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

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

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

Не пытайтесь заставить один использовать не оптимальные варианты или вы будете запутанными неопытными программистами

3

Извините за necroing этой старой нити. Существует фактически способ узнать размер времени компиляции массива.Это звучит примерно так:

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

В качестве альтернативы, если вы ненавидите таНос/новый, то вы можете создать размер шаблонный класс вместо этого. Хотя, я бы не рекомендовал его, и синтаксис довольно уродлив.

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

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

+2

Вы мастер – zaratustra

+0

В C++ 11 превосходный метод определения размера встроенного массива использует функцию шаблона constexpr. Например: template constexpr std :: size_t size (const T (& array) [N]) { return N; } – Ricky65

25

Вы люди имеют так усложненной это. Конечно, вы можете сделать это на 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! 
    } 
Смежные вопросы