Какъв е обхватът на литерална стойност и как компилаторът разпределя памет за нея?

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
Не мисля, че това е правилно, @Seth. Класовете са дефинирани в стандарта под 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 Разликата между екземплярите на класа, които са обекти, и екземплярите на вградените компоненти, които не са обекти, е джаваизъм. Не се отнася за 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.

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

Недефинирано до компилатора.
Но би било наистина лесно да се разпредели малко повече памет върху рамката на стека и да се задържи там. След това го унищожете и намалете размера на рамката на стека (въпреки че този отговор прави много предположения за основния хардуер, които никога не трябва да правите (най-добре просто да мислите за това като за компилатор, който прави магия)).

Какъв е обхватът на временен обект?

Временният обект живее до края на израза (обикновено ;), освен ако не е обвързан с const препратка. Ако е обвързан с константна препратка, тогава той живее до края на обхвата, към който принадлежи и препратката (с няколко изключения (като конструктори)).

Защо не можем да получим адреса му с &12 в неговия обхват?

Във въпроса 12 не е временен обект.
Това е литерал на цяло число.

person Martin York    schedule 20.12.2011
comment
Локи, полезен отговор, благодаря. @skjaidev и Локи, BTW, има ли някаква специална причина компилаторът да съхранява 12 в обектния файл, а не в RAM? - person Aquarius_Girl; 20.12.2011
comment
@AnishaKaul: 12 е литерал на цяло число, вероятно не се съхранява никъде (част е от кода). Променливата x е област на съхранение (обект) и следователно е адресируема, независимо дали тази средна RAM е напълно недефинирана. Вашият проблем е, че мислите от гледна точка на определени хардуерни изисквания. Стандартът умишлено се опитва да избегне спецификата на хардуера (като концепцията за RAM). Променливата 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, компилира или стандарта c++? - person Aquarius_Girl; 20.12.2011
comment
Стандартът умишлено не уточнява нищо подобно (Опитва се да бъде много хардуерен агностик). Следователно всичко зависи от компилатора. - person Martin York; 20.12.2011
comment
Този отговор е специфичен за C++. За функцията C връщанията никога не са lvalues. - 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 НЕ се поставя в RAM? - person Aquarius_Girl; 20.12.2011
comment
да Опитайте, можете да генерирате машинен код, еквивалентен на вашия c код с gcc -S foo.c. След това вижте генерирания foo.S файл. - person jman; 20.12.2011
comment
ще го пробвам Мога ли да предположа, че всичко, което е в обектния файл, не се съхранява в RAM? - 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