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

int x = 12;

12 называется целочисленным литералом и поэтому не может использоваться в LValue.

  1. Как компилятор выделяет память для литералов?
  2. Какова область видимости литералов?
  3. Почему мы не можем получить его адрес с &12 в области видимости?

person Aquarius_Girl    schedule 20.12.2011    source источник
comment
Э-э, 12 вообще не объект, как и x. Вы можете выбрать лучший пример, например, настоящий объект.   -  person paxdiablo    schedule 20.12.2011
comment
12 не является временным объектом - уж точно не в C и, вероятно, не в C++. Это просто начальное значение для x. Статус x не определен, потому что мы не можем видеть контекст, в котором он определен. (Или, если то, что вы показываете, это все, что есть, это глобальная переменная.)   -  person Jonathan Leffler    schedule 20.12.2011
comment
Это интегральный литерал - см. ответ skjaidev.   -  person paxdiablo    schedule 20.12.2011
comment
Целые числа @paxdiablo также являются объектами, как и все остальное   -  person Seth Carnegie    schedule 20.12.2011
comment
Я не думаю, что это правильно, @Сет. Классы определены в стандарте под 3.9.2 Compound Types вместе с массивами, функциями, определенными указателями и ссылками. Фундаментальный тип находится в 3.9.1 и здесь определены такие вещи, как int, float` и char.   -  person paxdiablo    schedule 20.12.2011
comment
x действительно называет объект в рамках объектной модели C++. Он создается определением, имеет продолжительность хранения и тип. См. § 1.8 Объектная модель C++ в стандарте C++11. В вопросе ясно, что термин «объект» используется в этом смысле, а не в смысле объекта в объектно-ориентированном программировании.   -  person bames53    schedule 20.12.2011
comment
Хорошо, очевидно, это недоразумение с моей стороны, хотя для стандарта необычно не быть более осторожным со своими терминами, чем это :-)   -  person paxdiablo    schedule 20.12.2011
comment
@paxdiablo соответствующая цитата - §1.8.1. Конструкции в программе C++ создают, уничтожают, ссылаются на объекты, получают к ним доступ и манипулируют ими. Объект представляет собой область хранения.   -  person Seth Carnegie    schedule 20.12.2011
comment
@paxdiablo, C имеет в основном эквивалентное определение объекта.   -  person AProgrammer    schedule 20.12.2011
comment
@paxdiablo Разве x не является объектом класса int?   -  person Aquarius_Girl    schedule 20.12.2011
comment
@AnishaKaul: int - это тип, а не класс. В C нет такого понятия, как класс; в C++ тип класса — это агрегатный тип, объявленный с использованием struct, class или union.   -  person Mike Seymour    schedule 20.12.2011
comment
@pax Различие между экземплярами класса, являющимися объектами, и экземплярами встроенных модулей, не являющимися объектами, - это Javaism. Это не относится к C++, где экземпляр любого типа обычно называется объектом.   -  person sbi    schedule 21.12.2011
comment
@JonathanLeffler 12 не является временным объектом - определенно не в C и, вероятно, не в C++. Действительно, буквальное целое число также не относится к объекту в C++.   -  person curiousguy    schedule 21.12.2011


Ответы (6)


OK Плохой пример в вопросе.
Но вопрос по-прежнему актуален:
Давайте попробуем:

Foo getFoo() {return Foo();}

int func()
{
    getFoo().bar();   // Creates temporary.
    // before this comment it is also destroyed.
    // But it lives for the whole expression above
    // So you can call bar() on it.
}

int func2()
{
    Foo const& tmp = getFoo();  // Creates temporary.
                                // Does not die here as it is bound to a const reference.

    DO STUFF
}  // tmp goes out of scope and temporary object destroyed.
   // It lives to here because it is bound to a const reference.

Как компилятор выделяет память для временного объекта?

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

Какова область действия временного объекта?

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

Почему мы не можем получить его адрес с &12 в области видимости?

В вопросе 12 нет временного объекта.
Это целочисленный литерал.

person Martin York    schedule 20.12.2011
comment
Локи, Полезный ответ, спасибо. @skjaidev и Локи, кстати, есть ли какая-то особая причина, по которой компилятор хранит 12 в объектном файле, а не в ОЗУ? - person Aquarius_Girl; 20.12.2011
comment
@AnishaKaul: 12 - это целочисленный литерал, который, вероятно, нигде не хранится (это часть кода). Переменная x является областью хранения (объектом) и, следовательно, является адресуемой, независимо от того, означает ли это среднее ОЗУ или нет, полностью не определено. Ваша проблема в том, что вы мыслите с точки зрения конкретных аппаратных требований. Стандарт намеренно пытается избежать аппаратной специфики (например, концепции оперативной памяти). Переменная x должна иметь физический адрес только в том случае, если ее адрес используется; он может просто жить в регистре (но это отвлекает от аппаратных особенностей, которые не рассматриваются в стандарте). - person Martin York; 20.12.2011
comment
12 is an integer literal it is probably not stored anywhere Возможно, поэтому мы получаем ошибку, если пишем 12 напрямую, а не присваиваем его чему-то. Итак, литералы типа 12 нигде не хранятся, это ответ? Значит ли это, что 12 не записывается в объектный файл, но записывается значение переменной, содержащей 12? - person Aquarius_Girl; 20.12.2011
comment
@AnishaKaul: int main() {12;} компилируется нормально. Поскольку 12 является литералом, то это действительное выражение, которое является допустимым утверждением. Имейте в виду, что это мало что делает. Литерал 12, вероятно, закодирован в ассемблерной инструкции в объектном файле. Переменная x у вас - это объект, который существует (вероятно, в памяти). - person Martin York; 20.12.2011
comment
Спасибо за информацию, Локи. Зависит ли это поведение от компилятора или от стандартов C99? - person Aquarius_Girl; 20.12.2011
comment
Я тоже не совсем уверен, что вы имеете в виду. - person Martin York; 20.12.2011
comment
Я имел в виду, кто решает, как и где хранить 12, компилятор или стандарт С++? - person Aquarius_Girl; 20.12.2011
comment
Стандарт намеренно не определяет ничего подобного (он пытается быть очень независимым от аппаратного обеспечения). Таким образом, все зависит от компилятора. - person Martin York; 20.12.2011
comment
Этот ответ специфичен для С++. Для функций C возврат никогда не является lvalue. - person Jens Gustedt; 20.12.2011

В вашем примере 12 является целочисленным литералом. Целочисленные литералы почти всегда «встроены» в машинные инструкции как непосредственный операнд. Они не хранятся в памяти, поэтому вы не можете получить к ним доступ через адрес и адрес, и у них нет области действия.

int x = 12 

переведет на что-то вроде

movl 12 address_of_x_or_register

практически во всех архитектурах. Здесь 12 закодировано как часть инструкции.

Просто чтобы было ясно, x все еще находится в памяти (стеке в случае локальных переменных или сегменте данных в случае глобальных переменных) и в конечном итоге будет содержать значение 12. «Объект» RHS 12 представляет собой целочисленный литерал и не находится в памяти до или во время инструкции, а «находится» в самой инструкции.

person jman    schedule 20.12.2011
comment
Итак, во время компиляции что компилятор делает с ним? Хранилище? - person Aquarius_Girl; 20.12.2011
comment
@skjaidev что означает BSS? Что-то-что-раздел, я бы предположил - person Seth Carnegie; 20.12.2011
comment
Компилятор использует значение непосредственно в машинной инструкции, хотя это только для целых чисел. Например, строковым литералам назначается место для хранения в сегменте данных. - person jman; 20.12.2011
comment
@skjaidev Вы хотите сказать, что компилятор во время фактической компиляции кода напрямую помещает 12 в результирующий объектный файл? 12 НЕ помещается в оперативную память? - person Aquarius_Girl; 20.12.2011
comment
Да. Попробуйте, вы можете сгенерировать машинный код, эквивалентный вашему коду C, с помощью gcc -S foo.c. Затем посмотрите сгенерированный файл foo.S. - person jman; 20.12.2011
comment
Я попробую это. Могу ли я предположить, что все, что попадает в объектный файл, не сохраняется в ОЗУ? - person Aquarius_Girl; 20.12.2011
comment
@AnishaKaul: Нет, ты не можешь сделать такое предположение. - person Martin York; 20.12.2011
comment
Просто для ясности: x все еще находится в памяти (стеке в случае локальных переменных или сегменте данных в случае глобальных сегментов) и содержит значение 12 после выполнения инструкции. Значение RHS 12 не находится в памяти до/во время инструкции, а находится в самой инструкции. - person jman; 20.12.2011

1. How does the compiler allocate memory to a temporary object?

string myString = "hello";

В этом случае вызывается conversion constructor для инициализации нового объекта.

2. What is the scope of a temporary object?

Срок жизни временного объекта до точки с запятой

3. Why can't we get its address with an &12 in its scope? (in this case "hello")

&12 не является объектом, это параметр, передаваемый конструктору преобразования

person Sanish Gopalakrishnan    schedule 20.12.2011
comment
&12 is not an object, it is the parameter given to the conversion constructor Почему мы не можем получить адрес 12 с помощью &12? - person Aquarius_Girl; 20.12.2011
comment
и что такое конструктор преобразования? - person Aquarius_Girl; 20.12.2011
comment
Эта ссылка будет полезна для понимания конструктора преобразования publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/ - person Sanish Gopalakrishnan; 20.12.2011
comment
См. этот вопрос SO, почему вы не можете взять адрес числового литерала stackoverflow.com/questions/1166378/ - person Sanish Gopalakrishnan; 20.12.2011
comment
Вторая ссылка показывает, почему вы МОЖЕТЕ взять адрес литерала, а не наоборот. :( - person Aquarius_Girl; 20.12.2011

Итак, во время компиляции что компилятор делает с ним? Хранилище?

Это действительно трудно ответить. Компилятор максимально оптимизирует код (объем или уровень выполняемой оптимизации часто можно установить в вашем инструменте компилятора).

Для примера, подобного приведенному, если x можно заменить в инструкциях по сборке на 12, тогда x «оптимизируется», и 12 используется как прямая замена x.

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

person spearson    schedule 20.12.2011

Объект - это "что-то в памяти". Это означает, что это что-то занимает часть адресного пространства процесса (либо в стеке, либо в «свободной» памяти). Также это означает, что вы можете получить его адрес, если хотите.

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

void f(const string&);

void g()
{
     f(string("Hello"));
}

Выражение, которое вызывает f(), приведет к генерации кода, который:

  • создает временный строковый объект. Конструктор вызывается с параметром const char*;
  • вызывает f() со ссылкой на этот временный объект в качестве параметра;
  • уничтожает временный строковый объект.

Ключевой частью этого является уничтожение временного объекта в конце оценки выражения. Временный объект существует только в самом выражении (это их импровизированная область). Вы можете попробовать что-то вроде: const string* ps = &string("Hello") но ваш компилятор, вероятно, забьет тревогу, потому что такое выражение приведет к созданию указателя, который ссылается на память, которая была занята временным объектом, но больше им не занята. Он может по-прежнему содержать элементы строкового объекта или может быть перезаписан следующими выражениями в программе (не говоря уже о том, что уничтожение временного объекта освободит память, выделенную объектом в куче). Использование ps приведет к неопределенному поведению.

Другой вопрос, который здесь возникает, касается природы объектов в таком выражении, как int x = 12. В этом случае x может быть объектом или может не быть. Это зависит от настроек компилятора и кода, следующего за строкой. Компилятор может решить поместить x в регистр. В таком случае x не будет объектом, потому что регистры не имеют адресов (по крайней мере, на большинстве платформ). Если вы не измените значение x, компилятор может даже захотеть использовать 12 напрямую в инструкциях. Таким образом, «12» будет существовать только как часть кодов инструкций.

В любом случае, что бы ни происходило в следующем коде, int x = 12 не создаст временный объект 12. Если компилятор решит разместить в памяти 12, инструкция будет выглядеть так (псевдокод):

store immediate address_of_x, 12

В случае x, помещенного в регистр, вы будете иметь:

move immediate regX, 12

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

person Pavel Zhuravlev    schedule 20.12.2011
comment
Временный объект существует только в самом выражении (это их импровизированная область действия). временные объекты не имеют имени, поэтому у них нет связанной области действия. - person curiousguy; 21.12.2011
comment
@curiousguy Вот почему я назвал это временным прицелом. Временный объект существует, пока вычисляется выражение. Аналогично названный объект существует, пока программа остается в его области. - person Pavel Zhuravlev; 22.12.2011

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

Какова область видимости литералов?

Этот вопрос не имеет смысла, так как область действия является свойством имен (имена переменных, имена функций, имена типов, имена шаблонов, имена пространств имен...).

Литерал — это обозначение числа, а не имени.

person curiousguy    schedule 21.12.2011