2013-11-19 3 views
1

В чем разница между следующими обозначениями?Различия между обозначениями массива

int * arrayA = new int[5]; 
int arrayB[5]; 

Я знаю, что первая строка будет возвращать тип указателя в то время как вторая строка возвращает int[] типа - но то, что происходит внутри? Как бы программно определить количество элементов arrayA?

+7

'int [5] arrayB;' не является законным, вы имеете в виду 'int arrayB [5];' – john

+0

@john: Упс, исправлено. – Daniel

+0

Вы не можете определить длину массива во время выполнения ... В C, в отличие от Java, массивы не отслеживают их собственные длины. Вы должны сами отслеживать длину. – Alderath

ответ

4

Разница заключается в том, что arrayB представляет собой массив с автоматической продолжительности хранения (~ в стеке, если это локальная переменная), в то время как arrayA является указателем на первый элемент массива с динамической продолжительности хранения (~ в куче) ,

Количество элемент arrayB может быть определена следующим образом:

template <class T, size_t N> 
size_t getElementCount(T (&)[N]) { return N; } 

int main() { 
    assert(getElementCount(arrayB) == 5); 
} 

Количество элемент arrayA может не быть определена. Он не сохраняется в любом месте, доступном для вашей программы.

+2

Счетчик элементов для 'arrayB' также может быть определен с помощью операции' sizeof (arrayB)/sizeof (arrayB [0]) '(пока массив B не был разложен). Размер 'arrayA' * известен * при его создании, поэтому его не нужно« определять ». –

3

Первый динамически распределяет память. Срок службы массива длится до тех пор, пока вы его не освободите (delete [] arrayA;). На практике никогда не было причин для этого; просто используйте std::vector<int> (так что вам не о чем беспокоиться delete).

Второй создает массив как локальную переменную. Он прекратит существование , когда переменная выходит за рамки. Если для некоторой причины вы не можете использовать std::vector, тогда предпочитайте это решение.

Что касается размера массива: в первом случае это до вас, чтобы управлять им. Что касается языка, то все, что у вас есть, является указателем. Во втором случае вы можете получить размер , используя стандартные функции std::end(arrayA ) - std::begin(arrayA) (по крайней мере, на C++ 11). Или, если вы используете , передавая его другой функции, вы можете передать его по ссылке; если другая функция является шаблоном (например, template <size_t N> void func(int (&array)[N])), компилятор будет создавать экземпляр с нулевым размером . Если это не шаблон (например, void func(int (&array)[5])), компилятор будет жаловаться, если размер не равен .

+0

+1: вместо этого замена 'arrayB' будет лучше обслуживаться' std :: array'. –

+1

@ZacHowland Вероятно, по крайней мере, в его сценарии. (Единственный раз, когда я использую что-либо, кроме 'std :: vector', когда я хочу полностью статическую инициализацию с компилятором, считающим инициализаторы. Это одна вещь, которую' std :: array' не поддерживает.) –

3

Я думаю, что вы имеете в виду

int arrayB[5]; 

вместо

int [5] arrayB; 

, поскольку последний не является юридическим C++ декларации. Такое объявление используется в C#.

В этом случае

int * arrayA = new int[5]; 

безымянный массив создается в куче и адрес первого элемента массива присваивается указатель Arraya. Переменная arrayA ничего не знает о том, сколько элементов вы выделили.Например, эти две переменные ниже, имеют один и тот же тип

int *array1 = new int[5]; 
int *array2 = new int[10]; 

Во втором случае

int arrayB[5]; 

переменная arrayB обозначает массив из 5 элементов типа Int. он имеет тип int [5] и знает, что он имеет 5 элементов. Например, int [5] и int [10] - два разных типа.

+0

Спасибо Vlad , Я уже исправил обозначение в своем оригинальном посте. – Daniel

3

В чем разница между следующими обозначениями?

Первый выделяет динамический массив и дает вам указатель на него. Вам понадобится удалить массив (delete [] p), когда он вам больше не понадобится, иначе память просочится. Обычно лучше не использовать исходные указатели для управления динамическими ресурсами, так как сложно проверить, правильно ли они удалены. Предпочитают RAII классы, такие как std::vector<int> для управления ресурсом автоматически.

Второй объявляет массив в любой области видимости, в которой появляется объявление. Если это внутри функции, оно имеет время автоматического хранения и будет автоматически уничтожено, когда оно выходит за рамки. Если он находится вне функции, он имеет статический срок хранения и будет автоматически уничтожен в конце программы.

Как бы программно определить количество элементов массива B?

В C образом:

size_t arrayB_size = sizeof arrayB/sizeof arrayB[0]; 

или в C++ образом:

template <typename T, size_t N> size_t array_size(T(&)[N]) {return N;} 
size_t arrayB_size = array_size(arrayB); 

Обратите внимание, что вы не можете определить размер динамического массива - эта информация теряется. Первый стиль даст фиктивный результат (основанный на размере указателя, а не массива), а второй не скомпилируется. Это еще одна причина для переадресации vector, которая знает его размер.

Смежные вопросы