Где хранятся временные объекты?

Правда ли, что временные объекты хранятся в динамической памяти (куче)?


person Mihran Hovsepyan    schedule 02.02.2012    source источник
comment
ИМО? Почему это было твое мнение? Что привело вас к такому предположению?   -  person underscore_d    schedule 19.12.2017


Ответы (4)


Стандарт не требует для них какой-либо области памяти (кучи/стека), но они аналогичны локальным переменным «автоматического хранения», то есть в конце выражения (или дольше, когда они связаны с ref-to-const). разрушаются.

Большинство реализаций будут хранить их в стеке, как локальные переменные.

изменить:

Как отметил Джеймс Канце: «В случае, если время жизни временного объекта продлевается с помощью ссылки на константу, его место хранения в большинстве реализаций в некоторой степени определяется местом хранения этой ссылки. То есть в случае, если ссылка находится в статическом хранилище, временная тоже будет (просто подтверждена на gcc). (хотя ИМХО, хотя это все еще временно в смысле стандартов, спорно, является ли это временным в интуитивном английском смысле этого слова)

person PlasmaHH    schedule 02.02.2012
comment
-1 и я объясню почему. Область видимости не обязательно является концом выражения, даже если она не привязана к константной ссылке, но благодаря оптимизации она может расширяться еще больше. Смотрите мой ответ. - person Luchian Grigore; 02.02.2012
comment
@LuchianGrigore: Итак, в вашем примере временный объект будет существовать после возврата foo();? Вы можете привести цитату из стандарта, где это разрешено? - person PlasmaHH; 02.02.2012
comment
@Luchian Grigore Здесь stackoverflow.com/questions/9018778/ говорит, что это должен быть конец выражения, не так ли? - person Mihran Hovsepyan; 02.02.2012
comment
@PlasmaHH да - 12,2/2. Также см. этот вопрос «передача временного объекта в качестве параметра по значению называется конструктором копирования»> stackoverflow.com/questions/8451212/ - person Luchian Grigore; 02.02.2012
comment
@PlasmaHH И я не говорил, что переменная существует после функции. Я только сказал, что время жизни может выходить за пределы конца выражения при передаче временного параметра в качестве параметра. - person Luchian Grigore; 02.02.2012
comment
@PlasmaHH в случае foo( A() ) временное может быть построено непосредственно в области действия функции и использовано в функции напрямую вместо создания копии. - person Luchian Grigore; 02.02.2012
comment
@LuchianGrigore Если это неверно, это означает, что выражение int x = foo(); имеет неправильный формат, поскольку возможно, что временное, созданное с помощью foo(), удаляется до инициализации x => это не является неправильным, поскольку приведенное выше выражение не имеет неправильного формата. - person Mihran Hovsepyan; 02.02.2012
comment
@PlasmaHH, а в случае возврата вы можете сделать return A();, а временное не копировать и не уничтожать, так как может произойти оптимизация возвращаемого значения. Поищи это. - person Luchian Grigore; 02.02.2012
comment
@MihranHovsepyan Я опубликовал ссылку на стандарт, подтверждающий то, что я сказал. Этого должно быть достаточно. - person Luchian Grigore; 02.02.2012
comment
@LuchianGrigore: 12.2/2 — это пример, в котором рассказывается о возможных способах хранения временных файлов и оптимизациях, которые могут привести к их полному исчезновению. Нигде не говорится о продлении жизни временного. Исключение копии не продлевает срок службы временного объекта, а исключает временное. Также обратите внимание, что это всего лишь примерный раздел и, следовательно, не нормативный, вам нужно будет процитировать нормативный текст, в котором говорится, где время жизни временного объекта может быть продлено до тех пор, пока не будет выполнена оценка выражения вызова функции. - person PlasmaHH; 02.02.2012
comment
@PlasmaHH, если мы собираемся быть анальными (ха-ха), стандарт не говорит, находится ли какой-либо временный объект в стеке, куче или чем-то еще. - person Luchian Grigore; 02.02.2012
comment
@PlasmaHH Но я понимаю твою точку зрения. Вы говорите, что если эта оптимизация и произойдет, то она уже не будет называться временной. Я согласен и удалил отрицательный голос. Тем не менее, я все еще думаю, что делаю хорошее замечание. - person Luchian Grigore; 02.02.2012
comment
Есть несколько случаев, когда его почти наверняка нет в стеке. Рассмотрим что-то вроде static MyType const& x = MyType();. В этом случае (и это единственный случай, который я могу придумать) временные данные, вероятно, будут находиться в том же пространстве, что и статические данные. - person James Kanze; 02.02.2012
comment
@JamesKanze: Действительно, я только что проверил gcc, и он находится в статике. Поэтому, может быть, лучше сказать, что в случае, если ссылка на константу продлевает время жизни, место хранения в некоторой степени определяется этой ссылкой. - person PlasmaHH; 02.02.2012
comment
@плазма этого недостаточно. увидеть ниже. - person Johannes Schaub - litb; 02.02.2012

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

Объекты-исключения, представляющие выброшенный объект во время раскручивания, также являются временными. Обычно они находятся в куче.

person Johannes Schaub - litb    schedule 02.02.2012
comment
Следует отметить, что мой ответ игнорирует наличие локальных переменных потока. кто-то опытный с этим должен высказаться и разъяснить. - person Johannes Schaub - litb; 02.02.2012
comment
Действительно, хотя ОП, вероятно, не имел в виду их, исключения тоже временные. Как и списки инициализаторов в C++11. Что касается локальных переменных потока, то, по крайней мере, на x86_64/linux они будут храниться в специальном сегменте памяти, доступ к которому осуществляется с помощью сегментного регистра gs, который устанавливается по-разному для каждого потока. - person PlasmaHH; 02.02.2012
comment
Являются ли объекты-исключения временными? Или что-то совсем другое. (В §3.7 стандарт перечисляет четыре длительности хранения: статическое, потоковое, автоматическое и динамическое. Я часто задавался этим вопросом: временные объекты явно имеют разную продолжительность, как и объекты-исключения.) - person James Kanze; 02.02.2012
comment
@James, вполне разумно выделить хранилище временных файлов с полным выражением в стеке на время жизни окружающего блока, даже если фактическое время жизни временного объекта потенциально значительно короче. Это простая для реализации модель, разрешенная спецификацией C++. Пример в конце 12.2p5 говорит о временных файлах со статической продолжительностью хранения. К сожалению, продолжительность статического хранения иногда используется в спецификации для вещей, где она не предназначена для соответствия временным (например, в определении ссылочного константного выражения). - person Johannes Schaub - litb; 03.02.2012
comment
Комитет ответил на ваш отчет о дефекте, что в настоящее время они не видят никаких действий, поскольку ничто в спецификации, по-видимому, не вызывало проблем, когда временные файлы имеют статическую или автоматическую продолжительность хранения (предположительно, потому что любое использование упомянутой переменной продолжительности хранения XXX, которая не мешает временным файлам, потому что временные файлы не являются переменными). Но определение ссылки и постоянного выражения адреса относятся к объектам со статической продолжительностью хранения, которые действительно соответствуют временным объектам. - person Johannes Schaub - litb; 03.02.2012

Это сильно зависит от реализации, но они, вероятно, находятся в автоматическом хранилище.

Обратите внимание, что область действия может быть нелогичной из-за оптимизации.

Следующее:

class A
{
//...
};

//....

A foo()
{
   A a;
   return a;
}

Здесь объект a не обязательно находится только внутри области действия функции, но может иметь место RVO.

Кроме того, при передаче по значению временного объекта он может быть уничтожен не сразу.

void foo(A a);
//...

foo( A() );

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

person Luchian Grigore    schedule 02.02.2012

Большинство (если не все) реализаций хранят их в стеке (т.е. в автоматическом хранилище), хотя я не думаю, что стандарт где-либо предписывает. Это, безусловно, проще сделать так, поскольку компилятор должен гарантировать время жизни временной переменной, и возможно, что указанное время жизни будет охватывать рекурсивный вызов той же функции, создавая другой экземпляр временной переменной.

person Tom Tanner    schedule 02.02.2012