Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

  • в стеке, если они auto -matic function-local variables
  • в куче, если они выделены с помощью new или malloc и т.д. (подробности о том, что означает "переменная хранится в куче" в комментариях)
  • в области данных каждого процесса, если они глобальны или static

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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

стопка:

int x;

кучного:

int *p = new int;

Как говорится, обе структуры построены в ОЗУ.

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

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

Ответ 5

С++ не знает о вашем кэше процессора.

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

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

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 8

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

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

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

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

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

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

Динамическое распределение не поддерживается переменными 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;
 }

Ответ 9

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

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

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