Почему указатели указывают на память, а не на ценность? - PullRequest
1 голос
/ 05 ноября 2011

В настоящее время я изучаю указатели в своем классе C ++ Algorithms, и хотя я понимаю материал, я не понимаю, почему C ++ указывает указателям на ячейку памяти, а не только на определенное значение, которое вы можете изменить позже.

Может показаться, что вы захотите динамически создать новую переменную в том самом слоте памяти, который занимает ваш указатель.

Это потому, что операционная система создает все динамические переменные в куче, и нам нужен способ их найти, потому что наш указатель создается при загрузке программы?

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

Ответы [ 5 ]

2 голосов
/ 05 ноября 2011

Память фактически сохраняется в случае, когда у вас есть большие объекты (под большими я имею в виду больше 4 или 8 байтов, то есть sizeof(void *)).Вместо того, чтобы платить за дорогостоящие операции копирования и перезаписи, вы просто передаете указатель, который меньше объекта, и назначаете его таким образом.

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

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

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

Вы всегда можете повторно использовать указатели.Например, если я выделю пространство для 100-байтового массива, я всегда могу использовать его повторно, пока у меня есть указатель на него, пока я не освобождаю его, пока я не закончу с этим пространством (вы на самом делерекомендуется сделать это).

1 голос
/ 05 ноября 2011

Чтобы добавить к другим хорошим ответам немного, я думаю, что понимание того, как работают компьютеры, также может помочь понять указатели и зачем они нам нужны.По моим собственным словам - каждая логическая операция в компьютере выполняется процессором (в самом простом случае, конечно).Сам процессор имеет очень мало памяти.Например, 32-битный i386 ЦП имеет 8 регистров , на которые он может работать, где каждый регистр может содержать только 4 байта данных (32-битных).Таким образом, 32 байта - это все, что может уместиться в CPU.Остальные данные хранятся в других схемах , таких как кэш процессора , RAM и т. Д. Поэтому, когда вы хотите, чтобы процессор что-то делал, вы должны попросить его:загружать данные из внешних цепей, и именно здесь вам нужно «указать» CPU на то, что именно вы хотите, чтобы он загружал, и вы должны дать ему «адрес» памяти.А указатели C - это именно те адреса, которые обеспечивают наименьший уровень адресации ячеек памяти на таких языках высокого уровня.

Теперь все в вашей программе размещено где-то в памяти (даже регистры ЦП технически являются памятью)., но они адресованы по разному).Будь то какое-то значение в стеке или динамически выделенная область памяти (в конце концов, стек также динамически выделяется), и вы всегда можете ссылаться на эти объекты по их адресам в памяти.Сам указатель - это значение (4 байта на i386 или 8 на amd64), которое содержит адрес чего-либо (и да, вы также можете указать на это значение, создав указатель на указатель).Так что указатели есть везде, даже если вы их не видите.Например, когда вы копируете какой-то большой «объект», должна быть выделена память для хранения копии этого объекта, а затем ЦП должен быть проинструктирован копировать байты из области памяти источника в область памяти назначения, побайтноОбращаясь к этим байтам через указатели (то есть здесь - это то, как фактические инструкции ЦП могут выглядеть в ассемблере).

Даже в очень высокоуровневых языках, таких как Java, указатели повсюду.Они просто скрыты от разработчиков.

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

1 голос
/ 05 ноября 2011

Ваш вопрос лучше всего проиллюстрировать примерами кода и контрастами A / B.(Это довольно абстрактно, как сказано, и трудно понять, что вы могли бы иметь в виду.)

C ++ предлагает вам выбор для размещения вещей в «стеке» или «динамически»:

/* foo is an integer on "the stack" */
int foo = 1;

/* bar is a pointer on "the stack", *bar is an integer on "the heap" */
int* bar = new int (1); 

И bar, и &foo указывают на целые числа, значение которых 1.Верно сказать, что bar потребляет память не только для этого целого числа, но и для переменной стека, которая отслеживает указатель на него.

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

При прочих равных условиях не следует использовать динамическое распределение.Программисты на C ++ часто пытаются убедить программистов на C переосмыслить свой код, чтобы он ему не понадобился.Однако эта «дополнительная память для хранения указателя» является наименьшей из ваших проблем с точки зрения того, почему следует избегать практики.В основном это сваливающаяся ответственность за то, чьей работой в конечном итоге будет выполнять delete ...

0 голосов
/ 05 ноября 2011

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

Вы задаетесь вопросом, почему C ++ «заставляет указатели указывать на слот памяти, а не только на определенное значение, которое вы можете изменить позже». Но слот в памяти - фактически единственное действительное место для хранения значения! Разумно сказать, что все данные в вашей программе хранятся в огромной группе слотов. Это как огромный массив.

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

Я также хочу сказать, как вы говорите: «Казалось бы, вы хотели бы иметь возможность динамически создавать новую переменную в том самом слоте памяти, который занимает ваш указатель».

Место, которое занимает указатель, заполняется адресом, где находится значение указателя (где он «указывает»). Если бы вы создали новую переменную в этом слоте, вы бы потеряли все знания о том, куда указывает указатель! Поэтому важно, чтобы в этом слоте памяти было необходимое нам значение.

"Это потому, что операционная система создает все динамические переменные в куче, и нам нужен способ их найти, потому что наш указатель создается при загрузке программы?"

Я не совсем уверен, что вы подразумеваете под "динамической переменной", но нет, не все указатели хранятся в куче. Простой пример:

int a = 5;
int *b = &a;

Обратите внимание, что b - это указатель, который указывает на a, но и a, и b находятся в стеке, а не в куче.

Если под динамическим вы имеете в виду «созданный с помощью new», то да, будет справедливо сказать, что все вещи, созданные с помощью новых, создаются в куче.

Еще одно важное замечание: операционная система (как правило) не управляет распределением памяти. Максимум, что он сделает, - это даст вам большой кусок памяти, чтобы делать все, что вы захотите. Если вам интересно, проверьте подпрограмму C под названием malloc, которая является способом выделения памяти в куче, очень похоже на new. За этим на самом деле не так много магии.

0 голосов
/ 05 ноября 2011

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

Если так, то зачем вам указатели?Также обратите внимание, что указатели являются предложением «два в одном», при этом, указывая на область памяти, вы также можете получить доступ к значению в указанной памяти, например,

int a;
int *b;
b=&a;

 b >> memmory location
*b >> value

и здесьхороший учебник для вас: Указатели и память

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...