ВСТУП
ISOC ++ 11 (офіційно ISO / IEC 14882: 2011) - це найновіша версія стандарту мови програмування C ++. Він містить деякі нові функції та поняття, наприклад:
- rvalue посилання
- xvalue, glvalue, категорії значень вираження prvalue
- переміщення семантики
Якщо ми хотіли б зрозуміти поняття нових категорій значень виразів, ми повинні мати на увазі, що існують посилання rvalue та lvalue. Краще знати, що значення можуть бути передані посиланням, що не мають значення rvalue.
int& r_i=7; // compile error
int&& rr_i=7; // OK
Ми можемо отримати певну інтуїцію понять ціннісних категорій, якщо цитувати підрозділ під назвою Lvalues and rvalues з робочого проекту N3337 (найбільш схожий проект із опублікованим стандартом ISOC ++ 11).
3.10 Значення та оцінки [basic.lval]
1 Вирази класифікуються відповідно до систематики на рисунку 1.
- Значення lvalue (так називалося історично, тому що lvalues могли з'являтися в лівій частині виразу присвоєння) позначає функцію або об'єкт. [Приклад: Якщо E - вираз типу вказівника, то * E - це вираження значення, яке посилається на об'єкт або функцію, на яку вказує E. В якості іншого прикладу, результат виклику функції, типом повернення якої є посилання lvalue, є значення. —Закінчити приклад]
- Значення xvalue (значення "eXpiring") також відноситься до об'єкта, як правило, наприкінці його терміну (наприклад, для переміщення його ресурсів). Значення xvalue є результатом певного виду виразів, що містять посилання rvalue (8.3.2). [Приклад: Результатом виклику функції, типом повернення якої є посилання rvalue, є xvalue. —Закінчити приклад]
- Glvalue («узагальнений» lvalue) - це значення або xvalue.
- Rvalue (так називається історично, тому що rvalues можуть з'являтися в правій частині виразу присвоєння) - це xvalue,
тимчасовий об'єкт (12.2) або його суб'єкт, або значення, яке не
пов'язане з об'єктом.
- Першозначення ("чисте" значення) - це оцінку, яка не є xvalue. [Приклад: Результат виклику функції, тип повернення якої не є
посиланням, є первинним значенням. Значення буквального типу, такого як 12, 7.3e5 або
true, також є першим значенням. —Закінчити приклад]
Кожен вираз належить саме до однієї з основних класифікацій у цій систематиці: lvalue, xvalue або prvalue. Ця властивість виразу називається його ціннісною категорією.
Але я не зовсім впевнений, що цього підрозділу достатньо для чіткого розуміння понять, тому що "зазвичай" насправді не є загальним, "наприкінці терміну його життя" насправді не є конкретним, "з участю посилань на реальну оцінку" не зовсім зрозуміло, та "Приклад: Результатом виклику функції, тип повернення якої є посилання rvalue, є значення xva." звучить, як змія кусає хвіст.
ОСНОВНІ КАТЕГОРІЇ ЦІННОСТІ
Кожен вираз належить точно до однієї категорії первинних значень. Ці категорії значень - категорії lvalue, xvalue та prvalue.
значення
Вираз E належить до категорії lvalue тоді і лише тоді, коли E посилається на сутність, котра ВИНАГА мала ідентифікацію (адресу, ім'я чи псевдонім), що робить її доступною поза межами E.
#include <iostream>
int i=7;
const int& f(){
return i;
}
int main()
{
std::cout<<&"www"<<std::endl; // The expression "www" in this row is an lvalue expression, because string literals are arrays and every array has an address.
i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
i; // ... as the entity the expression i in this row refers to.
int* p_i=new int(7);
*p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
*p_i; // ... as the entity the expression *p_i in this row refers to.
const int& r_I=7;
r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
r_I; // ... as the entity the expression r_I in this row refers to.
f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
i; // ... as the entity the expression f() in this row refers to.
return 0;
}
xvalues
Вираз E належить до категорії xvalue тоді і лише тоді, коли він є
- результат виклику функції, неявно чи явно, тип повернення якого є посилання, що оцінюється на тип об'єкта, що повертається, або
int&& f(){
return 3;
}
int main()
{
f(); // The expression f() belongs to the xvalue category, because f() return type is an rvalue reference to object type.
return 0;
}
- переклад на рецензію посилання на тип об'єкта, або
int main()
{
static_cast<int&&>(7); // The expression static_cast<int&&>(7) belongs to the xvalue category, because it is a cast to an rvalue reference to object type.
std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).
return 0;
}
- вираз доступу члена класу, що позначає нестатичний член даних нереференційного типу, в якому вираженням об'єкта є xvalue, або
struct As
{
int i;
};
As&& f(){
return As();
}
int main()
{
f().i; // The expression f().i belongs to the xvalue category, because As::i is a non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.
return 0;
}
- вираз вказівника на члена, в якому перший операнд є xvalue, а другий операнд - вказівник на член даних.
Зауважте, що ефект з правил, наведених вище, полягає в тому, що названі посилання rvalue на об'єкти трактуються як lvalues, а неназвані посилання rvalue на об'єкти трактуються як xvalues; rvalue посилання на функції трактуються як значення як ім'я чи ні.
#include <functional>
struct As
{
int i;
};
As&& f(){
return As();
}
int main()
{
f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
As&& rr_a=As();
rr_a; // The expression rr_a belongs to the lvalue category, because it refers to a named rvalue reference to object.
std::ref(f); // The expression std::ref(f) belongs to the lvalue category, because it refers to an rvalue reference to function.
return 0;
}
prvalues
Вираз E належить до категорії первинного значення тоді і лише тоді, коли Е не належить ні до значення, ні до категорії xvalue.
struct As
{
void f(){
this; // The expression this is a prvalue expression. Note, that the expression this is not a variable.
}
};
As f(){
return As();
}
int main()
{
f(); // The expression f() belongs to the prvalue category, because it belongs neither to the lvalue nor to the xvalue category.
return 0;
}
КАТЕГОРІЇ СМІШЕНОЇ ЦІННОСТІ
Є ще дві важливі категорії змішаної вартості. Ці категорії значень - це категорії rvalue та glvalue.
оцінки
Вираз E належить до категорії rvalue тоді і лише тоді, коли E належить до категорії xvalue, або до категорії первинного значення.
Зауважте, що це визначення означає, що вираз E належить до категорії rvalue тоді і лише тоді, коли E посилається на сутність, яка не мала ідентичності, що робить її доступною поза E EET.
гливослови
Вираз E належить до категорії glvalue тоді і лише тоді, коли E належить до категорії lvalue або до категорії xvalue.
ПРАКТИЧНЕ ПРАВИЛА
Скотт Мейєр опублікував дуже корисне правило, щоб відрізнити оцінки від значення.
- Якщо ви можете взяти адресу виразу, вираз є значенням.
- Якщо тип виразу є посиланням на значення (наприклад, T & або const T & тощо), це вираження є значенням.
- В іншому випадку вираз є оцінкою. Концептуально (а зазвичай і фактично) rvalues відповідають тимчасовим об'єктам, таким як поверненим з функцій або створеному за допомогою неявного перетворення. Більшість буквальних значень (наприклад, 10 і 5.3) також є rvalues.