2008-10-23 3 views
12

Где хранятся переменные в C++?Где хранятся переменные в C++?

Внутри ОЗУ или кэш процессора?

+0

Этот вопрос не имеет смысла, так как (большинство) кэша являются прозрачными и действительно просто часть системы памяти. Это также неверно, потому что это действительно зависит от архитектуры и компилятора, где хранятся переменные C++ (или любые скомпилированные языки). – tgamblin 2008-10-23 17:26:12

+0

Кроме того, заголовок вопроса может быть значительно улучшен – jonner 2008-10-23 18:24:56

+1

@Tal, как говорили другие, как говорится, вопрос нечеткий. Может быть, вы хотите посмотреть на комментарии людей и посмотреть, можете ли вы задать более конкретный вопрос. – 2008-10-23 18:27:29

ответ

1

Переменные могут храниться в разных местах, иногда в нескольких местах. Большинство переменных помещаются в ОЗУ при загрузке программы; иногда переменные, объявленные const, вместо этого помещаются в ПЗУ. Всякий раз, когда к переменной обращаются, если она не находится в кэше процессора, возникает ошибка кэша, и процессор останавливается, когда переменная копируется из RAM/ROM в кеш.

Если у вас есть подходящий оптимизирующий компилятор на полпути, локальные переменные часто будут храниться в файле регистра процессора. Переменные будут перемещаться между ОЗУ, кешем и регистром, поскольку они читаются и записываются, но обычно они всегда будут иметь копию в RAM/ROM, если компилятор не решит, что это необязательно.

6

Переменные в C++ хранятся либо в стеке, либо в куче.

стек:

int x; 

кучи:

int *p = new int; 

При этом, обе структуры, построенные в оперативной памяти.

Если ваша оперативная память высока, хотя Windows может заменить ее на диск.

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

0

в зависимости от того, как они были объявлены, они будут либо храниться в «heap» или «stack»

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

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

34

Переменные сохраняются:

  • в стеке, если они auto -matic функции локального переменных
  • в куче, если они выделяются с new или malloc и т.д. (подробности что это значит сказать «переменная хранится в куче» в комментариях)
  • в области данных в процессе, если они являются глобальными или static

Это все в ОЗУ, конечно. Кэширование прозрачно для процессов пользовательского пространства, хотя оно может заметно повлиять на производительность.

Компиляторы могут оптимизировать код для хранения переменных в регистрах. Это очень компилятор и зависит от кода, но хорошие компиляторы будут делать это агрессивно.

8

Переменные обычно хранятся в ОЗУ. Это либо в куче (например,все глобальные переменные обычно идут туда) или в стек (все переменные, объявленные в методе/функции, обычно идут туда). Стек и куча - это ОЗУ, только разные местоположения. Указатели имеют разные правила. Указатель на что-то (блок памяти, объект и т. Д.) Сам обычно следует правилам выше (указатель, объявленный внутри функции, хранится в стеке), но данные, на которые он указывает (сам блок памяти или объект вы создали с новым) хранится в куче. Вы можете создать указатели, указывающие на стек (например, «int a = 10; int * b = & a;», b указывает на a, а a - в стеке), но выделение памяти с использованием malloc или new рассчитывается в память кучи.

Что входит в процессорный кеш, не соответствует управлению компиляторами, процессор решает, что нужно кэшировать и как долго его кэшировать (в зависимости от таких факторов, как «Используются ли эти данные?» Или «Ожидается ли, что данные используются довольно скоро снова? »и, конечно, размер кеша имеет большое влияние на то, как долго процессоры будут хранить данные там - чем больше у них кеша, тем больше данных они могут кэшировать и чем дольше они могут хранить данные там прежде чем освободить пространство кэша для новых данных).

Компилятор может решить только, попадают ли данные в регистр CPU. Обычно данные хранятся там, если к ним обращаются очень часто подряд (поскольку доступ к регистру быстрее, чем кэш, и намного быстрее, чем ОЗУ). Некоторые операции над некоторыми системами могут выполняться только в том случае, если данные находятся в регистре, однако компилятор будет решать, копировать ли данные обратно в ОЗУ сразу после выполнения операции на нем или хранить его там, чтобы выполнить еще много операций на нем перед тем, как записать его обратно в ОЗУ. Он всегда будет пытаться хранить наиболее часто используемые данные в регистре, если это возможно, и если в нем заканчиваются регистры (в зависимости от количества регистров вашего процессора), он будет решать, лучше ли записывать данные в ОЗУ (и выборка это оттуда, когда это необходимо снова) или просто временно поменять данные на стек, а затем вытащить их обратно (даже если стек также является ОЗУ), обычно использование стека происходит быстрее, поскольку у процессоров обычно есть вершина кэша кэша в любом случае, поэтому нажимать и выскакивать из стека на самом деле может быть только запись в кеш и чтение оттуда, данные могут никогда не появляться в памяти вообще). Однако, когда поток кода перескакивает от одного метода/функции к другому, обычно все регистры записываются обратно в память, поскольку компилятор не может с уверенностью сказать, что вызываемая функция/метод не будет обращаться к памяти, в которой поступают данные регистра и когда не записывая данные назад, функция может видеть старое значение, все еще присутствующее в памяти, поскольку новое значение находится только в регистре и еще не записано.

15

Для C++ в целом правильный ответ - «везде, где ваш компилятор решает поставить их». Вы не должны делать предположения иначе, если вы каким-либо образом не скомпилируете свой компилятор. Некоторые переменные могут быть полностью сохранены в регистрах, а некоторые могут быть полностью оптимизированы и заменены буквально где-то. С некоторыми компиляторами на некоторых платформах константы могут фактически оказаться в ПЗУ.

Часть вашего вопроса о «кеше процессора» немного сбита с толку. Существуют некоторые инструменты для управления обработкой процессора кешем, но в целом это бизнес процессора и должен быть невидим для вас. Вы можете представить себе кеш как окно вашего процессора в ОЗУ. Довольно много любой доступ к памяти проходит через кеш.

На другом конце уравнения неиспользуемая оперативная память иногда выгружается на диск на большинстве ОС. Таким образом, это возможно (но маловероятно), что в некоторые моменты ваши переменные фактически хранятся на диске. :-)

3

Я думаю, что вы смешиваете две концепции. Во-первых, как язык C++ хранит переменные в памяти. Во-вторых, как компьютер и операционная система управляют этой памятью.

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

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

5

C++ не знает о кеше вашего процессора.

Когда вы запускаете программу, написанную на C++ или любом другом языке, ваш процессор будет хранить копию «популярных» фрагментов ОЗУ в кеше. Это делается на аппаратном уровне.

Не думайте, что кеш процессора как «другая» или «более» память ... это всего лишь механизм, позволяющий хранить некоторые куски ОЗУ.

1

Язык C++ поддерживает два вида распределения памяти через переменные в программах C++:

Статическое распределение является то, что происходит, когда вы объявляете статическую или глобальную переменную. Каждая статическая или глобальная переменная определяет один блок пространства фиксированного размера. Пространство выделяется один раз, когда ваша программа запускается (часть операции exec) и никогда не освобождается. Автоматическое распределение происходит при объявлении автоматической переменной, такой как аргумент функции или локальная переменная. Пространство для автоматической переменной выделяется при вводе составного оператора, содержащего объявление, и освобождается при выходе этого составного оператора. Размер автоматического хранилища может быть выражением, которое меняется. В других реализациях CPP он должен быть константой. Третий важный вид распределения памяти, динамическое распределение, не поддерживается переменными C++, но доступен в библиотечных функциях. Распределение динамической памяти

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

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

Или вам может понадобиться блок для каждой записи или каждого определения во входных данных; так как вы не можете заранее знать, сколько будет, вы должны выделить новый блок для каждой записи или определения по мере его чтения.

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

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

Например, если вы хотите динамически выделять некоторое пространство для хранения структуры foobar, вы не можете объявить переменную типа struct foobar, содержимое которой является динамически распределенным пространством. Но вы можете объявить переменную типа указателя struct foobar * и присвоить ей адрес пространства. Затем вы можете использовать операторы «*» и «->» на этом переменный указатель на ссылаться на содержимое пространства:

{ 
    struct foobar *ptr 
     = (struct foobar *) malloc (sizeof (struct foobar)); 
    ptr->name = x; 
    ptr->next = current_foobar; 
    current_foobar = ptr; 
} 
Смежные вопросы