Необходимо ли е да има временен или литерал, за да има rvalue?

Този въпрос пита дали всички временни елементи са rvalue.

Отговорът е не, защото ако разгледаме този израз:

const int &ri = 2 + 3;

след това същият временен (2 + 3), който тук е rvalue, може да се използва като lvalue в следващ израз:

const int *pi = &ri;

така че това временно не е (само) rvalue.

Тогава логическото твърдение temporary ==> rvalue е невярно.

Ние обаче не можем да пишем

const int &ri = &(2 + 3); // illegal, 2 + 3 -> temporary -> rvalue

or

int *i = &4; // illegal, 4 is an rvalue (literal)

or

int foo();
int *i = &foo(); // illegal, foo() -> temporary -> rvalue

По този начин въпросът ми е можем ли да генерираме rvalue в определен израз, без да имаме временен или литерал? Вярно ли е rvalue ==> (temporary or literal)?


person Vincenzo Pii    schedule 03.11.2012    source източник


Отговори (2)


Изразите, които дават временни обекти, са r-стойности. Има специално правило, което позволява на const-препратките и r-стойностите да се свързват с r-стойностите и това удължава живота на временния обект до този на препратката (вижте 12.2(5)), но това не прави временния -обектен израз по-малко от r-стойност.

Въпреки това, веднъж обвързана с препратка, самата референтна променлива има име и по този начин референтният израз е l-l стойност.

Не бъркайте изрази, променливи и обекти.

person Kerrek SB    schedule 03.11.2012
comment
Не бъркайте изрази, променливи и обекти: Правилно. l-стойност и r-стойност се прилагат към изрази. Временните елементи не са r-стойности, израз, който дава временна е израз с r-стойност - person David Rodríguez - dribeas; 03.11.2012
comment
@DavidRodríguez-dribeas: Да, наистина – добре казано. - person Kerrek SB; 03.11.2012
comment
Това, което се казва в 12.2(5), потвърждава, че temporary ==> rvalue е невярно и това е добре. Но все пак нямам пример, който да показва, че rvalue ==> (temporary or literal) е невярно. Както казах на Дейвид, не предизвиквам, а просто се опитвам да разбера дали това твърдение (rvalue ==> (temporary or literal)) може да бъде направено. Благодаря. - person Vincenzo Pii; 03.11.2012
comment
@VincenzoPii: Много неща са rvalues. Например разпаднали имена на C масиви. Или this. Или резултат от определен статичен каст. - person Kerrek SB; 03.11.2012
comment
@VincenzoPii: Като добавим към тези примери, израз lvalue, използван в контекст, където е необходима rvalue, ще бъде преобразуван в rvalue с ( очевидно име): преобразуване от lvalue към rvalue. int a = 5; int b = 1+a;, подизразът a е lvalue, който ще бъде преобразуван в rvalue, така че в тази конкретна употреба a е rvalue, както споменах преди: помислете, че lvalue е препратка към реален обект, докато rvalue е просто стойност (която може или не може да се съхранява в обект). - person David Rodríguez - dribeas; 05.11.2012

Атрибутите rvalue и lvalue се прилагат към изрази, а не към обекти. Един израз може да бъде или lvalue, или rvalue. Прекомерното опростяване на израз, който дава стойност, е rvalue-expression, а израз, който дава обект, е lvalue-expression. Преобразуването на lvalue в rvalue е актът на четене на стойността от обект.

Израз, който дава временен и литерал, са rvalue-expressions, те представляват стойност, а не действителен обект.

Във вашия пример:

const int &ri = 2 + 3;
const int *pi = &ri;

Изразът 2+3 е rvalue-expression, използван за инициализиране на константна препратка. Това според езика предполага удължаване на живота на временния над текущия израз и докато препратката излезе извън обхвата. След това във втория израз подизразът ri е lvalue-expression, който препраща към временния обект, чийто живот е удължен.

Имайте предвид, че има други начини за създаване на rvalue изрази с временни елементи, например извикване на член, който дава препратка:

struct test {
   test& thisTest() { return *this; }
};
test foo();
... foo().thisTest()

Подизразът foo() е rстойностен израз, но изразът foo().thisTest() е lстойностен израз. И двата се отнасят до временен обект, който ще изчезне в края на пълния израз.

person David Rodríguez - dribeas    schedule 03.11.2012
comment
Благодаря Ви за отговора. В последния ви пример демонстрирате, че temporary ==> rvalue е невярно, но не и че rvalue ==> (temporary or literal) е невярно. Необходимо ли е да има временен или литерал, за да се поддаде на rvalue? Не те предизвиквам, просто искам да разбера дали можем да направим такова твърдение :). - person Vincenzo Pii; 03.11.2012
comment
@VincenzoPii: Пропускате смисъла. rvalue и lvalue се прилагат към изрази, а не към обекти. Обект, който не е временен, може да се използва в контекста, където е необходима rvalue и това ще задейства преобразуването lvalue към rvalue и вие ще използвате обект като rvalue. r/l-стойността е свързана само с временните/именувани обекти, тъй като изразите, които включват едното или другото, обикновено са от същия тип. За пример за несвързана кола: Jaguar/Volkswagen не са свързани с газ/дизел, въпреки че има само един дизелов модел Jaguar (така че не са 100% ортогонални) - person David Rodríguez - dribeas; 05.11.2012
comment
Благодаря много за обяснението, вече е напълно ясно! - person Vincenzo Pii; 05.11.2012