2013-05-25 4 views
2

Я изучаю C++, и у меня есть вопрос о указателях.Создайте указатель на стеке

У меня есть этот код:

int* max = new int; 
*max = 0; 

Я думаю, я создал указатель на куче (если я не прав, пожалуйста, скажите мне).

Один вопрос:

Есть ли способ, чтобы создать инициализировать указатель с одной командой? (теперь я использую две инструкции).

Другой вопрос:

Как я могу создать указатель на стек?

Я вижу код, как это:

int myVar = 20; 
int* pVar = &myVar; 

Я думаю, что я не создал указатель на стек, но я думаю, что это единственный способ не создать указатель на кучу.

Я очень очень новичок в разработке на С ++.

+3

Ваш второй фрагмент кода действительно создает int в стеке и указатель на этот int в стеке. –

+0

просто пишите «new int (0)». Посмотрите здесь: http://en.wikipedia.org/wiki/New_%28C++%29 – Markon

+7

«Я думаю, я создал указатель на кучу» Нет, вы создали «int» в куче и указатель на стек, который указывает на это 'int'. – leemes

ответ

7
int* max = new int; 

выше строка создает указатель на стеке и инициализирует его с целым числом, хранящимся в куче. Всякий раз, когда new участвует в выражении, он возвращает указатель на его динамически созданный операнд:

в соответствии с пунктом 5.3.4/2 C++ 11 Стандарт на:

объектов, созданных с помощью new -выражения имеют динамическую продолжительность хранения (3.7.4). [-] Если объект является объектом без массива, новое выражение возвращает указатель на созданный объект. Если это массив, то выражение new возвращает указатель на исходный элемент массива.

int myVar = 20; 
int* pVar = &myVar; 

В этом примере, как указатель и его значение сохраняется в стеке. A new -expression не участвовал в задании, поэтому в этой кучке ничего не создается в куче.

Если вы хотите инициализировать значение заостренный-объекта в одной строке, вы должны значение инициализации это примерно так:

int* max = new int(5); 

или в C++ 11 вы можете использовать единообразную инициализацию:

int* max = new int{5}; 

также важно, что вы помните, чтобы delete то, что вы создали с new. Поскольку память находится в динамическом распределении, ее время жизни не зависит от области, в которой она была создана. Если вы забудете delete, ваша программа получит утечку памяти.

delete max; 

И если max был указатель установлен на массив, созданный с помощью new -expression, вы бы использовать delete[]:

delete[] max; 

Примечание: Если указатель был не проинициализирована new -expression, тогда нет необходимости удалять.

Обычно вам рекомендуется использовать контейнеры для хранения багажа для вас. Что-то вроде std::unique_ptr сделаю. После того, как его деструктор, память он держит удаляется:

std::unique_ptr<int> max{new int{5}}; 

В C++ 14 мы имеем make_unique:

auto max = std::make_unique<int>(5); 
0

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

int *iptr = new int(20); 

оно инициализируется значением 20;

Стек: содержит локальные переменные. поэтому, когда вы создаете указатель и назначаете его локальным объектам. указывая на переменные в стеке. мы не создаем указатель на кучу .

8

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

Ваш первый код выделяет пробел на кучу, который может содержать int. Вы сохраняете указатель на эту память на стек.

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

Так оба указатели на стек, но только второй указывает на стек.

В обоих случаях тип, который вы назначаете, является примитивным типом.Примитивные типы не инициализируются по-умолчанию, если вы сразу не присвоить ему значение (ваш второй код), или использовать синтаксис конструктора, который также работает с кучей распределённых значений:

int *max = new int(0); 

Тем же синтаксис может быть используется в вашем втором коде, кстати:

int myVar(20); 

в случае, если вы заинтересованы: вы можете также определить указатели на куче. int* тип указателей на int с, так что просто идти вперед и выделить такой тип в куче:

new int*(); 

Это выражение возвращает int**, который затем можно хранить где-то. Опять же, как правило, хранить этот указатель на указатель на стеке:

int **pointerToPointer = new int*(); 

Как int с, вы можете инициализировать в новом экспрессии в какой-то указатель на междунар (здесь в int*, с max указателем сверху):

int **pointerToPointer = new int*(max); 

Теперь у вас есть два указатели с одинаковым адресом: max (указатель на стек) и некоторый указатель на куче, которые вы указываете при помощи pointerToPointer, т.е. имеет место следующее (I разыменования `pointerToPointer, что приводит к оценке е хранится за этим указателем, который является указателем на целое число):

max == *pointerToPointer 
2

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

да:

int * a = new int(20); //initialized with 20; 

Как я могу создать указатель на стек?

int myVar = 20; 
int* pVar = &myVar; //copied your code snipped It's alright 
+0

'pVar' является указателем * на * стек, а не на * на * стеке, если я не ошибаюсь – Mifeet

+0

@Mifeet: на самом деле это оба: указатель на стек, указывающий на значение в стеке. – syam

+0

год, право, должно было больше времени задуматься :) – Mifeet

0

Ваш первый пример

int* max = new int; 
*max = 0; 

действительно создавая new int в куче, и ваша переменная max сохраняет указатель на этот int. Если вы собираетесь использовать это, вам придется использовать delete max;, когда вам больше не нужно, чтобы избежать утечек памяти.

Второй пример

int myVar = 20; 
int* pVar = &myVar; 

создает Int в стеке, pVar теперь указатель на адрес, где ИНТ сохраняется в памяти. Однако, если вы используете это, вам не нужно удалять pVar, потому что его нет в куче (вы не использовали ключевое слово new).

Основное различие между двумя переменными (созданными в куче и стеке) состоит в том, что переменная стека будет автоматически удаляться при ее удалении. Область определяются фигурными скобками {}:

int* somefnc() 
{ 
    int e1 

    { 
     int* e2 = new int(0); 
     int e3 = 0; 
    } // int e3 gets automatically deleted here 

    return e2; 
} // e1 gets automatically deleted here 

// e2 still exists and has to be manually deleted. 

Одним из преимуществ указателей при работе с массивами. Если вы должны были создать массив символов из x элементов в стеке, вам нужно знать количество элементов во время компиляции. Если вы хотите создать массив символов из x элементов во время выполнения с динамическим количеством элементов, вам нужно будет использовать char* ar = new char[x];, а затем получить к нему доступ на ar[x-1] = '\n';.


Для того, чтобы инициализировать переменную при ее создании на куче вы можете использовать var x = new var(args);.

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