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.
Как компилаторът разпределя памет за временен обект?
Недефинирано до компилатора.
Но би било наистина лесно да се разпредели малко повече памет върху рамката на стека и да се задържи там. След това го унищожете и намалете размера на рамката на стека (въпреки че този отговор прави много предположения за основния хардуер, които никога не трябва да правите (най-добре просто да мислите за това като за компилатор, който прави магия)).
Какъв е обхватът на временен обект?
Временният обект живее до края на израза (обикновено ;
), освен ако не е обвързан с const препратка. Ако е обвързан с константна препратка, тогава той живее до края на обхвата, към който принадлежи и препратката (с няколко изключения (като конструктори)).
Защо не можем да получим адреса му с &12 в неговия обхват?
Във въпроса 12 не е временен обект.
Това е литерал на цяло число.
x
е област на съхранение (обект) и следователно е адресируема, независимо дали тази средна RAM е напълно недефинирана. Вашият проблем е, че мислите от гледна точка на определени хардуерни изисквания. Стандартът умишлено се опитва да избегне спецификата на хардуера (като концепцията за RAM). Променливата 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