Неправильна форма:
int &z = 12;
Правильна форма:
int y;
int &r = y;
Питання :
чому перший код помилковий? Яке " значення " помилки в назві?
Неправильна форма:
int &z = 12;
Правильна форма:
int y;
int &r = y;
Питання :
чому перший код помилковий? Яке " значення " помилки в назві?
(ostringstream() << "x=" << x).str()
Відповіді:
C ++ 03 3.10 / 1 говорить: "Кожен вираз є або значенням l, або значенням r." Важливо пам’ятати, що lvalueness проти rvalueness - це властивість виразів, а не об’єктів.
Lvalues називає об'єкти, які зберігаються за межами одного виразу. Так , наприклад, obj
, *ptr
, ptr[index]
і ++x
все lvalues.
Rvalues - це тимчасові періоди, які випаровуються в кінці повного виразу, в якому вони живуть ("з крапкою з комою"). Так , наприклад, 1729
, x + y
, std::string("meow")
і x++
все rvalues.
Адреса оператора вимагає, щоб його "операнд був значенням". якщо ми могли б взяти адресу одного виразу, вираз є значенням, інакше це значенням r.
&obj; // valid
&12; //invalid
int & = 12;
недійсний, стандарт говорить, що рядковий літерал є значенням, інші літерали - значеннями r.
std::string("meow")
створює об'єкт типу std::string
і видає значення r, яке позначає цей об'єкт, 1729
не має побічного ефекту і дає значення 1729 р. Як значення типу int
.
"Lvalues name objects that persist beyond a single expression."
- це 100% правильне твердження. Навпаки, ваш приклад (const int &)1
неправильний, оскільки це НЕ "названий" об'єкт.
int &z = 12;
Праворуч тимчасовий об'єкт типу int
створюється із цілісного літералу 12
, але тимчасовий не може бути прив'язаний до посилання, що не є const. Звідси і помилка. Це те саме, що:
int &z = int(12); //still same error
Чому створюється тимчасовий? Оскільки посилання має посилатися на об'єкт у пам'яті, а для того, щоб об'єкт існував, його потрібно створити спочатку. Оскільки об'єкт не називається, це тимчасовий об'єкт. Він не має назви. З цього пояснення стало майже ясно, чому другий випадок добре.
Тимчасовий об'єкт може бути прив'язаний до посилання const, а це означає, що ви можете зробити це:
const int &z = 12; //ok
Для повноти я хотів би додати, що в C ++ 11 введено rvalue-reference, яке може прив'язуватися до тимчасового об'єкта. Отже, в C ++ 11 ви можете написати це:
int && z = 12; //C+11 only
Зверніть увагу, що існує &&
ціла кількість &
. Також зауважте, що const
це більше не потрібно, навіть якщо об’єкт, який z
прив’язується, є тимчасовим об’єктом, створеним із цілісного літералу 12
.
Оскільки C ++ 11 ввів rvalue-reference , int&
відтепер він називається lvalue-reference .
12
- константа часу компіляції, яку неможливо змінити на відміну від даних, на які посилається int&
. Що ви можете зробити, це
const int& z = 12;
void f( vector<int> const & )
, яка ідіоматично передає вектор, який не підлягає зміні. Зараз проблема полягає в тому, що f( vector<int>(5) )
це буде неправильно, і користувачеві доведеться забезпечити інше перевантаження, void f( vector<int> v ) { f(v); }
яке є тривіальним.
f( vector<int>(5) )
компілятор створює тимчасовий, а потім прив'язує посилання на цей тимчасовий, і так само якщо відбулося неявне перетворення 5
безпосередньо. Це дозволяє компілятору генерувати єдиний підпис для функції і дозволяє реалізацію функції для одного користувача. Відтепер подібна поведінка визначається для решти використання постійних посилань для узгодженості.
T const & r = *ptr;
будь-яке подальше використання r
у функції може бути замінено *ptr
і r
не повинно існувати під час виконання) або, можливо, його доведеться реалізувати, зберігаючи адресу об'єкта, який він псевдонім (розгляньте можливість збереження посилання як члена об'єкта) - який реалізований як вказівник на автоматичні посилання.
Ось правила мови С ++:
12
), є "значенням"int &ri = 12;
неправильно сформованоВи повинні розуміти, що це правила на C ++. Вони просто є.
Легко винайти іншу мову, скажімо C ++ ', з дещо іншими правилами. У C ++ 'дозволено створювати посилання, що не є const, зі значенням r. Тут немає нічого непослідовного чи неможливого.
Але це дозволило б зробити деякий ризикований код, коли програміст міг би не отримати те, що він задумав, і дизайнери С ++ справедливо вирішили уникнути цього ризику.
Посилання - це "приховані вказівники" (не нульові) на речі, які можуть змінюватися (lvalues). Ви не можете визначити їх як константу. Це має бути річ "змінної".
РЕДАГУВАТИ ::
Я думаю
int &x = y;
як майже еквівалент
int* __px = &y;
#define x (*__px)
де __px
- свіже ім'я, і #define x
працює лише всередині блоку, що містить декларацію про x
посилання.
const
:)
const