int x = 12;
12
называется целочисленным литералом и поэтому не может использоваться в LValue.
- Как компилятор выделяет память для литералов?
- Какова область видимости литералов?
- Почему мы не можем получить его адрес с &12 в области видимости?
int x = 12;
12
называется целочисленным литералом и поэтому не может использоваться в LValue.
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 нет временного объекта.
Это целочисленный литерал.
x
является областью хранения (объектом) и, следовательно, является адресуемой, независимо от того, означает ли это среднее ОЗУ или нет, полностью не определено. Ваша проблема в том, что вы мыслите с точки зрения конкретных аппаратных требований. Стандарт намеренно пытается избежать аппаратной специфики (например, концепции оперативной памяти). Переменная x
должна иметь физический адрес только в том случае, если ее адрес используется; он может просто жить в регистре (но это отвлекает от аппаратных особенностей, которые не рассматриваются в стандарте).
- person Martin York; 20.12.2011
12 is an integer literal it is probably not stored anywhere
Возможно, поэтому мы получаем ошибку, если пишем 12 напрямую, а не присваиваем его чему-то. Итак, литералы типа 12 нигде не хранятся, это ответ? Значит ли это, что 12 не записывается в объектный файл, но записывается значение переменной, содержащей 12?
- person Aquarius_Girl; 20.12.2011
int main() {12;}
компилируется нормально. Поскольку 12 является литералом, то это действительное выражение, которое является допустимым утверждением. Имейте в виду, что это мало что делает. Литерал 12, вероятно, закодирован в ассемблерной инструкции в объектном файле. Переменная x
у вас - это объект, который существует (вероятно, в памяти).
- person Martin York; 20.12.2011
В вашем примере 12
является целочисленным литералом. Целочисленные литералы почти всегда «встроены» в машинные инструкции как непосредственный операнд. Они не хранятся в памяти, поэтому вы не можете получить к ним доступ через адрес и адрес, и у них нет области действия.
int x = 12
переведет на что-то вроде
movl 12 address_of_x_or_register
практически во всех архитектурах. Здесь 12 закодировано как часть инструкции.
Просто чтобы было ясно, x
все еще находится в памяти (стеке в случае локальных переменных или сегменте данных в случае глобальных переменных) и в конечном итоге будет содержать значение 12
. «Объект» RHS 12 представляет собой целочисленный литерал и не находится в памяти до или во время инструкции, а «находится» в самой инструкции.
gcc -S foo.c
. Затем посмотрите сгенерированный файл foo.S
.
- person jman; 20.12.2011
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
не является объектом, это параметр, передаваемый конструктору преобразования
&12 is not an object, it is the parameter given to the conversion constructor
Почему мы не можем получить адрес 12 с помощью &12?
- person Aquarius_Girl; 20.12.2011
Итак, во время компиляции что компилятор делает с ним? Хранилище?
Это действительно трудно ответить. Компилятор максимально оптимизирует код (объем или уровень выполняемой оптимизации часто можно установить в вашем инструменте компилятора).
Для примера, подобного приведенному, если x можно заменить в инструкциях по сборке на 12, тогда x «оптимизируется», и 12 используется как прямая замена x.
Ключевое слово volatile можно использовать, чтобы заставить компилятор проверять x каждый раз, когда он используется в коде. Это создаст большие программы, но может быть полезно, чтобы помочь вам назначить место в памяти (хранилище) для вашей переменной.
Объект - это "что-то в памяти". Это означает, что это что-то занимает часть адресного пространства процесса (либо в стеке, либо в «свободной» памяти). Также это означает, что вы можете получить его адрес, если хотите.
Временные объекты — это просто объекты. Компилятор генерирует код для их создания, если ему нужны такие объекты для вычисления выражения:
void f(const string&);
void g()
{
f(string("Hello"));
}
Выражение, которое вызывает 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 будет частью инструкции (фрагмента скомпилированного кода). Таким образом, это не будет отдельным объектом.
Будьте осторожны, так как другие ответы в основном развеяли ваши заблуждения, но не этот:
Какова область видимости литералов?
Этот вопрос не имеет смысла, так как область действия является свойством имен (имена переменных, имена функций, имена типов, имена шаблонов, имена пространств имен...).
Литерал — это обозначение числа, а не имени.
12
вообще не объект, как иx
. Вы можете выбрать лучший пример, например, настоящий объект. - person paxdiablo   schedule 20.12.2011x
. Статусx
не определен, потому что мы не можем видеть контекст, в котором он определен. (Или, если то, что вы показываете, это все, что есть, это глобальная переменная.) - person Jonathan Leffler   schedule 20.12.20113.9.2 Compound Types
вместе с массивами, функциями, определенными указателями и ссылками. Фундаментальный тип находится в 3.9.1 и здесь определены такие вещи, какint,
float` иchar
. - person paxdiablo   schedule 20.12.2011x
действительно называет объект в рамках объектной модели C++. Он создается определением, имеет продолжительность хранения и тип. См. § 1.8 Объектная модель C++ в стандарте C++11. В вопросе ясно, что термин «объект» используется в этом смысле, а не в смысле объекта в объектно-ориентированном программировании. - person bames53   schedule 20.12.2011int
- это тип, а не класс. В C нет такого понятия, как класс; в C++ тип класса — это агрегатный тип, объявленный с использованиемstruct
,class
илиunion
. - person Mike Seymour   schedule 20.12.2011