2011-12-20 2 views
3
int x = 12; 

12 считается целочисленным литералом и поэтому не может использоваться в LValue.Какова область литерального значения и как компилятор выделяет ей память?

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

Err, '12' не является _объектом вообще, равно как и' x'. Вы можете выбрать лучший пример, например объект _real_. – paxdiablo

+2

12 не является временным объектом - конечно, не в C, и, возможно, и не на C++. Это просто начальное значение для 'x'. Статус 'x' является неопределенным, потому что мы не можем видеть контекст, где он определен. (Или, если вы показываете все, что есть, это глобальная переменная.) –

+0

Что такое 12? @paxdiablo –

ответ

4

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 не является временным объектом.
Это целостный литерал.

+0

Локи, полезный ответ, спасибо. @skjaidev и Loki, BTW, есть ли какая-то особая причина, что компилятор хранит 12 в объектном файле, а не в ОЗУ? –

+1

@AnishaKaul: 12 - целочисленный литерал, который, вероятно, не хранится нигде (это часть кода). Переменная 'x' является областью хранения (объект) и, таким образом, является адресной, вывешивает это среднее ОЗУ или нет полностью не определено. Ваша проблема в том, что вы думаете с точки зрения конкретных требований к оборудованию. Стандарт намеренно пытается избежать аппаратной специфики (например, концепции ОЗУ). Переменная 'x' должна иметь только физический адрес, если используется его адрес; он может просто жить в регистре (но это отвлекает от аппаратных особенностей, которые не рассматриваются в стандарте). –

+0

'12 - целочисленный литерал, который, вероятно, не хранится нигде'. Возможно, именно по этой причине мы получаем ошибку, если мы непосредственно пишем 12, а не присваиваем ее чему-то. Значит, литералы вроде 12 не хранятся нигде - это ответ? Значит ли это, что 12 не записывается в объектный файл, но значение переменной, которая содержит 12, получает? –

3

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

int x = 12 

бы перевести на что-то вроде

movl 12 address_of_x_or_register 

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

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

+0

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

+0

@skjaidev что означает BSS? Что-то-что-то секция Я бы догадался –

+1

Компилятор использует значение непосредственно в машинной инструкции, это только для целых чисел. Строковые литералы, например, назначаются хранилищем в сегменте данных. – jman

1

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

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

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

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

2

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 не является объектом, он не является параметром дано в конструктор преобразования

+0

'& 12 не является объектом, это параметр, заданный конструктору преобразования. Почему мы не можем получить адрес 12 с вопросом & 12? –

+0

и что такое «конструктор преобразования»? –

+0

Эта ссылка была бы полезна для понимания «конструктора преобразования» http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr384 .htm – Sanish

1

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

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

void f(const string&); 

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

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

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

Ключевой частью этого является уничтожение временного объекта в конце оценки выражения. Временный объект существует только в самом выражении (то есть их временном использовании scope). Вы можете попробовать что-то вроде: 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 

В случае х plased в регистрации у вас будет:

move immediate regX, 12 

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

+0

«_Temporary object существует только в самом выражении (то есть в их временной области) ._« временные объекты неназванные, следовательно, у них нет какой-либо связанной области ** – curiousguy

+0

@curiousguy Вот почему я назвал это ** временный объект существует во время оценки выражения.Аналогично названный объект существует, пока программа остается в своем объеме. –

1

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

Какова сфера применения литералов?

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

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