различие между двумя методами объявления массива c++
Это один из 2-х возможных способов объявления массивов (и выделения памяти для них) в c++
1. int a[3];
2. int *b = new int[3];
Я хочу понять, как c++ относится к этим двум по-разному.
A. В обоих случаях я могу обращаться к массиву со следующим синтаксисом: a[1] и b[1]
B. Когда я пытаюсь cout<< a и cout<< b, оба печатают адреса первого элемента соответствующих массивов.
Мне кажется, что и a, и b рассматриваются как указатели на первые элементы массивы.
Но странно, когда я пытаюсь сделатьcout << sizeof(a) и sizeof(b), они печатают разные значения - 4 и 12 соответственно.
Я не понимаю, почему в случае sizeof(b) печатается размер всего массива.
5 ответов:
aявляется массивом (типint [3])bявляется указателем (Типint*)В C++ это совершенно разные вещи.
Массив
Единственное, что объединяет массивы и указатели, - это то, что массивы часто "распадаются" на указатели в нескольких ситуациях. Вот что происходит, когда вы распечатываете их стоимость.sizeof- это число элементов, умноженное на размер каждого элемента.
УказательsizeofA не зависит от размера массива (обычно 4 или 8 байт).
Как вы заметили, это кажется, как будто оба
Разница между ними едва заметна при написании (или чтении) кода. Переменнаяaиbявляются указателями на начало массива. Но в действительности толькоbявляется указателем.aна самом деле является массивом.aрассматривается как регулярная переменная (так же, какintилиdouble), поскольку ей автоматически выделяется часть памяти. Для сравнения предположим, что вы объявилиint i. Переменнаяiявляется имя, данное определенному набору смежных байтов в памяти для хранения целого значения (4 байта на вашем компьютере). Аналогично,a- это имя, данное набору смежных байтов, который содержит Ваш массив (12 байт в вашем случае).В отличие от
Таким образом, это действительно два разных вида вещей. Это становится менее понятным для программистов C++. Одной из причин этого является тот факт, что вы можете использовать операторb- это только указатель на одно место в памяти. В вашем случае существует блок из 12 байт, который динамически выделяется (черезnew int[3]).bсам по себе является автоматически выделенным 4-байтовым указателем, который указывает на первыйintзначение в этом 12-байтовом блоке.[]для обоих типов. Другая причина заключается в том, что массивы неявно вырождаются в указатели в нескольких ситуациях (например, в функцииvoid Foo(int a[3]);,aна самом деле это не массив, а указатель на начало массива). Но не обманывайтесь - массивы-это, а не указатели (как утверждают многие люди), и указатели-это определенно не массивы.
1 выделяется в стеке. Массивы в стеке должны иметь размер, известный во время компиляции.
2 выделяется на куче. Массивы в куче не имеют такого требования. Помните, если вы выделяете с помощью
new[], вам нужно освободить его позже с помощьюdelete[]:int* b = new int[3]; delete[] b;
Массивы C++ в стеке имеют ограничение, которое
int array[10]; sizeof(array) needs to be compile-time constant and sizeof(array[0])==sizeof(array[1])==...==sizeof(array[9])Массивы C++ в куче имеют только 2-е ограничение, но не первое. (это позволяет определять размер массива во время выполнения)
Массивы стека (#1) имеют размеры, ограниченные стеком. Массивы кучи (#2) имеют размеры, ограниченные кучей (которая больше, чем стек).
Есть некоторые существенные преимущества производительности для распределения стека, посмотрите этот поток для получения дополнительной информации: Что быстрее: распределение стека или выделение кучи