Проблема с константными ссылками и временными объектами

Из C++ Primer я понял, что когда я привязываю константную ссылку к неконстантному объекту, ссылка привязывается к временному объекту, значение которого является неконстантным объектом.

int a = 1;
const int &b = a;
a = 2;
std::cout<<b;

Как я понял, будет создан временный объект const int со значением a, и b будет инициализирован с ним, так что как если бы я написал этот код:

int a = 1;
const int x = a;
const int &b = x;
a = 2;
std::cout<<b;

Первый код выводит 2, а второй — 1. Почему? Почему значение константной ссылки b изменилось с изменением a, тогда как на самом деле оно привязано к временному константному объекту, а не напрямую к a?


person Mason    schedule 19.03.2020    source источник
comment
Как я понял, будет создан временный объект const int со значением a, и b будет инициализирован с ним, так что, как будто я написал этот код Неверно. Никакое временное значение не задействовано. b относится непосредственно к a. b МОЖЕТ ссылаться на временное (и продлит срок службы этого временного), но это не то, что здесь происходит.   -  person user4581301    schedule 19.03.2020
comment
Замена std::cout<<b; на std::cout<<b<<"\n"; std::cout<<((a!=b)?a:b); показывает, что происходит?   -  person C. R. Ward    schedule 19.03.2020
comment
Посмотрите здесь: ideone.com/G8zmC2   -  person C. R. Ward    schedule 19.03.2020


Ответы (4)


Я понял, будет создан временный объект const int, значение которого равно a, и b будет инициализирован с ним,

Ты неправ. В этом фрагменте кода не создается временный объект.

int a = 1;
const int &b = a;

Более того, в стандарте C++ даже не указано, выделяется ли память для ссылки b.

Вы должны рассматривать ссылку b как псевдоним для переменной a.

Поскольку ссылка ссылается на объект a как на постоянный объект, вы не можете использовать ссылку для изменения объекта a. Тем не менее объект a объявлен как непостоянный объект. Таким образом, вы можете изменить его значение, например

a = 2;

но вы не можете изменить его, используя ссылку, например

b = 2;

Вы можете использовать ссылку для изменения значения объекта a, если ссылка была объявлена ​​как

int &b = a;

В этом случае результат этих двух утверждений

a = 2;

а также

b = 2;

будут эквивалентны.

Что касается этого фрагмента кода

int a = 1;
const int x = a;
const int &b = x;
a = 2;
std::cout<<b;

затем константе x присваивается копия значения переменной a. x и a — это два разных объекта, занимающих разный объем памяти.

Ссылка b объявлена ​​как ссылка на объект x.

const int &b = x;

Таким образом, изменение объекта a не влияет на значение константы x. Константа x не может быть изменена ни напрямую, ни с помощью ссылки b.

person Vlad from Moscow    schedule 19.03.2020

Вы путаете две разные вещи, о которых говорит учебник по С++.

Во-первых, вы используете термин «константная ссылка» для обозначения ссылки, которая сама по себе является постоянной. Это не то, что учебник C++ подразумевает под термином "константная ссылка". Как говорится:

ТЕРМИНОЛОГИЯ: ССЫЛКА НА КОНСТ - ЭТО ССЫЛКА НА КОНСТ
Программисты на C++ склонны бесцеремонно использовать термин ссылка на константу. Строго говоря, под "константной ссылкой" подразумевается "ссылка на константу". ... Это использование настолько распространено, что мы будем следовать ему и в этой книге.

Во-вторых, вы путаете примеры и правила, включающие разные базовые типы (double и const int), с примерами, включающими один и тот же базовый тип (int и const int).

Попробуйте это, чтобы получить эффект, который вы описываете:

double a = 42.0;
const int &b = a;
person David Schwartz    schedule 19.03.2020
comment
Спасибо за ответы. Я использовал термин ссылка на константу для обозначения ссылки на константу. В книге упоминается пример с различными базовыми типами после того, как в нем упоминаются примеры назначения константных ссылок на литералы и объекты одного и того же базового типа, поэтому я подумал, что все они имеют одинаковый случай. - person Mason; 19.03.2020

int a = 1;
const int x = a;  // x is a copy of a
const int &b = x;  // b is a reference to x, not a
a = 2;
std::cout<<b;

Во втором фрагменте b является ссылкой на x. (Обратите внимание, что x НЕ является ссылкой на a). Таким образом, изменение а не меняет х и, следовательно, не меняет b.

person cigien    schedule 19.03.2020

Привет @Мейсон,

int a = 1;
const int &b = a;
a = 2;
std::cout<<b;

Здесь переменная b привязана к постоянному адресу или «ссылке», то есть a. Вы можете делать с a все, что хотите, но если бы вы сделали:

int c = 7;
&b = c;

т.е. измените ссылку b, вы получите сообщение об ошибке. b будет содержать любое значение любого a as. Примерно так работает передача/вызов по ссылке.

int a = 1;
const int x = a;
const int &b = x;
a = 2;
std::cout<<b;

Вот, как сказал @cigien,

Во втором фрагменте b является ссылкой на x. (Обратите внимание, что x НЕ является ссылкой на a). Таким образом, изменение а не меняет х и, следовательно, не меняет b.

ваша переменная b не имеет отношения к a. Это связано / ссылается только на x, как и в первом коде это было на a. Здесь любое изменение a не влияет на x. Следовательно, это оправдывает ответ;)

Лучший.

person rasengan__    schedule 19.03.2020