c ++, что такое «указатель = новый тип», а не «указатель = новый тип []»? - PullRequest
16 голосов
/ 18 мая 2011

Во многих уроках первые примеры кода о динамической памяти начинаются со строк:

int * pointer;
pointer = new int;        // version 1
//OR
pointer = new int [20];    // version 2

Они всегда объясняют, как работает вторая версия, но полностью избегают разговоров о первой версии.

Что я хочу знать, что создает pointer = new int? Что я могу с этим сделать? Что это значит? Каждый урок в обязательном порядке позволит полностью не говорить о первой версии. Все, что я узнал (по поводу возни), это:

#include <iostream>

using namespace std;

int main()
{
    int * pointer;
    pointer = new int;
   pointer[2] = 1932;   // pointer [2] exists? and i can  assign to it?!
   cout << pointer[2] << endl;      // ... and access it successfully?!
};

Тот факт, что я могу использовать индекс pointer, говорит мне о том, что pointer = new int неявно создает массив. Но если так, то какой это размер?

Если бы кто-то мог помочь мне разобраться со всем этим, я был бы благодарен ...

Ответы [ 10 ]

13 голосов
/ 18 мая 2011

Это типичная ошибка в C и C ++ для начинающих. Первое предложение создает пространство для хранения только int. Второй создает пространство для хранения 20 из этих int с. Однако в обоих случаях он назначает адрес начала динамически зарезервированной области переменной pointer.

Чтобы добавить путаницу, вы можете получить доступ к указателям с индексами (как вы указали pointer[2]), даже когда указанная ими память недопустима. В случае:

int* pointer = new int;

вы можете получить доступ к pointer[2], но у вас будет неопределенное поведение. Обратите внимание, что вы должны проверить, что эти обращения на самом деле не происходят, и компилятор обычно мало что может сделать для предотвращения ошибок этого типа.

11 голосов
/ 18 мая 2011

Мой учитель объяснил это так.
Подумайте о кино.Фактические места - это распределение памяти, а билет, который вы получаете, - это указатели.

int * pointer = new int;

Это будет кинотеатр с одним местом, а указатель будет билетом на это место

pointer = new int [20] 
* 1007.* Это будет кинотеатр на 20 мест, а указатель - билет на первое место.указатель [1] будет билетом на второе место, а указатель [19] будет билетом на последнее место.

Когда вы набираете int* pointer = new int; и затем получаете доступ к pointer[2], вы позволяете кому-нибудь сесть.в проходе, что означает неопределенное поведение

9 голосов
/ 18 мая 2011

Это создает только одно целое число.

pointer = new int;        // version 1

Это создает 20 целых чисел.

pointer = new int [20]    // version 2

Ниже указано недопустимое значение, так как указатель [2] переводится как * (указатель + 2);который не был создан / выделен.

int main()
{
    int * pointer;
    pointer = new int;
   pointer[2] = 1932;   // pointer [2] exists? and i can  assign to it?!
   cout << pointer[2] << endl;      // ... and access it succesfuly?!
};

Приветствия!

2 голосов
/ 18 мая 2011

new int[20] выделяет память для целого числа массив размера 20 и возвращает указатель на него.

new int просто выделяет память для one integer и возвращает указатель на него.Неявно, это то же самое, что и new int[1].

. Вы можете разыменовать (т.е. использовать *p) оба указателя, но вы должны использовать p[i] только для указателя, возвращенного new int[20].

p[0] будет по-прежнему работать на обоих, но вы можете случайно ошибиться и поставить неверный индекс.

Обновление : Другое отличие заключается в том, что вы должны использовать delete[] для массива и delete для целого числа.

1 голос
/ 18 мая 2011

* «Тот факт, что я могу подписать указатель, говорит мне о том, что я pointer = new int неявно создает массив. Но если так, то какой это размер?» *

Это была часть вопроса, которая мне больше всего понравилась и на которую вы обращаете особое внимание.

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

void* operator new[] (std::size_t size) throw (std::bad_alloc);

Это фактически представляет массив объектов этого определенного размера, и если это успешно, то он автоматически Создает каждый из объектов в массиве.Таким образом, мы можем свободно использовать объекты в пределах размера, потому что он уже был инициализирован / сконструирован.

int * pointer = new int;

С другой стороны, для приведенного выше примера есть все возможности неопределенного поведения, когда любой из

*(pointer + k) or *(k + pointer)

.Хотя к определенной ячейке памяти можно получить доступ с помощью указателей, нет никакой гарантии, потому что конкретный объект для нее не был создан или создан. Это можно рассматривать как пространство, которое не было выделено в стеке для конкретной программы.

Надеюсь, это поможет.

1 голос
/ 18 мая 2011

pointer = new int; выделяет целое число и сохраняет его адрес в pointer. pointer[2] является синонимом pointer + 2. Чтобы понять это, прочитайте об арифметике указателей. Эта строка на самом деле является неопределенным поведением, потому что вы обращаетесь к памяти, которую ранее не выделяли, и она работает, потому что вам повезло.

1 голос
/ 18 мая 2011

pointer = new int выделяет достаточно памяти в куче для хранения одного int.

pointer = new int [20] выделяет память для хранения 20 int с.

Оба вызова возвращают указатель на вновь выделенную память.

Примечание: Не полагайтесь на инициализированную выделенную память, она может содержать случайные значения.

0 голосов
/ 18 мая 2011
int * pointer; pointer = new int;  // version 1
//OR 
pointer = new int [20]             // version 2 

я хочу знать, что создает pointer = new int? что я могу с этим сделать? что это значит? Каждый урок в обязательном порядке не будет говорить о первой версии целиком

Причина, по которой учебник не дает вам понять, что с ним делать, заключается в том, что он действительно совершенно бесполезен! Он выделяет один int и дает вам указатель на это.

Проблема в том, что если вам нужен int, почему бы вам просто не объявить его?

int i;
0 голосов
/ 18 мая 2011

Не создает массив.Он создает одно целое число и возвращает указатель на это целое число.Когда вы пишете указатель [2], вы ссылаетесь на память, которую вы не распределили.Вы должны быть осторожны и не делать этого.Эта память может быть отредактирована из внешней программы, которая, я считаю, вам не нужна.

0 голосов
/ 18 мая 2011

int* p = new int выделяет память для одного целого числа. Это не подразумевает создание массива. То, как вы обращаетесь к указателю с помощью p[2], приведет к неопределенному поведению при записи в недопустимую область памяти. Вы можете создать массив, только если вы используете синтаксис new[]. В таком случае вам нужно освободить память, используя delete[]. Если вы выделили память с помощью new, то это означает, что вы создаете отдельный объект, и вам нужно освободить память с помощью delete.

...