2015-09-07 2 views
3

я прочитал недавно на официальный документ на C++ 11, что если я пишу,Confused с г-значений и Л-значений

void foo(X&)

Это будет вызываться для л значений, но не для г -величины

и если я пишу,

void foo(const X&)

Это будет называться как для R-значение и L-значения.

Может ли кто-нибудь дать мне пример, что это значит?

ответ

4

Эта функция принимает Lvalue присвоенный

void foo(X&) 

и пытается вызвать его с RValue даст ошибку.

Эта функция ожидает, что ссылки на const именующих

void foo(const X&) 

, но есть улов:

Rvalue может быть использован для инициализации константной ссылки-значения, и в этом случае времени жизнь объекта определена по rvalue продолжается до тех пор, пока не закончится область действия ссылки.

из cppreference

Так это правда, что эта последняя функция принимает как Левое и параметры Rvalue

struct X {}; 

void foo(X&) { 
} 

void fooC(const X&) { 
} 

int main() { 
    X obj; 
    // foo(std::move(obj)); // Error - non-const 
    foo(obj); // Valid 
    fooC(obj); // Valid 
    fooC(std::move(obj)); // Valid 
} 

Для получения дополнительной информации посмотрите на здесь: reference initialization или проверить [dcl.init .ref]/p5

+1

Это хорошо, спасибо. – cpp11dev

1

Рассмотрите этот код:

int i = 58; 

Что такое 58? Это буквальный константа.

Следовательно: foo (const int&)

58 является г-значение (а также буквальный константа в данном случае), потому что вы не можете напрямую обратиться к нему и, скажем, изменить его, потому что нет никакого способа, чтобы сделать это , Вы можете обратиться к i, потому что у него есть имя, идентификатор, но 58 сам не имеет идентификатора.

Colloquially говоря, если что-то существует, но оно не имеет объявленную имя, которое вы можете получить доступ к его, то это постоянная и г-значение, если вы не ссылаться на него с г-валин эталонным междунар & &, то вы можете мутировать его ,

int f(); 
... 
int x = f(); //the returned int is an r-value, but x is an l-value 
+0

Ницца, мне понравилось ваше объяснение. – cpp11dev

+0

Тогда это очень помогло бы мне, если бы вы дали ему точку;) –

0

При объявлении функции Foo как

void foo(X&) 

то такой код не скомпилируется:

foo(5); 

Но если вы объявляете это нравится:

void foo(const X&) 

то могут называть это так:

foo(5); 

Соединительный литерал 5 является значением r, потому что у него нет имени.

0

Грубо говоря, rvalues ​​являются временными объектами (возвращенными из функции), а lvalues ​​- это объекты, которые вы также можете ссылаться.

Например:

X bar(); 

X x = bar(); 

в этом коде (игнорируя возможные оптимизации компилятора), временный объект X создается для хранения возвращаемого значения обув и передается x «s копирования конструктору, этот временный объект является rvalue, только живет внутри этого утверждения и не может ссылаться на другие части кода. x однако является lvalue, вы можете получить его адрес и обратиться к нему позже.

Обе функции

void foo(X &); 
void foo(const X &); 

ожидать lvalues, неконстантный и сопзИте соответственно. Причина, по которой позже принимает значения r, заключается в том, что rvalues ​​могут быть преобразованы в const-ссылки на lvalues. То есть, вы можете сделать это:

const X &ref = bar(); 

здесь временный возвращаемый баром() не разрушаются до ref выходит из области видимости, поэтому его срок службы был продлен за пределами заявления. Однако вы не можете сделать то же самое с неконстантными ссылками,

X &ref = bar(); // Error! 

это не допускается причиной возвращенного значения бара является временным (Rvalue) и не может быть изменен.

Обратите внимание, что это не функция C++ 11, это уже было. Новая функция является возможность указать RValue ссылки

void foo(X &&); 
void foo(const X &&); 

, который вводит еще более нюансами ситуации, смотри, например, Universal References in C++11 - Scott Meyers.

Смежные вопросы