5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
1

Ссылка на указатель на константу

01.10.2016, 22:13. Показов 3170. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер!

Не подскажите почему только выражение с pi_ref3 верное, а остальные - нет (VS 2013). Выражение с pi_ref1 вроде как-то логичнее для того, чтобы претендовать на верность. Тем не менее компилятор принимает только с pi_ref3:

C++
1
2
3
4
5
6
  const int ival = 1024;
 
  int* &pi_ref0 = &ival;
  const int* &pi_ref1 = &ival;
  int* const &pi_ref2 = &ival;
  const int* const &pi_ref3 = &ival;
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.10.2016, 22:13
Ответы с готовыми решениями:

Ссылка на указатель на константу
Подскажите почему неверна конструкция int *k=new int(10); int const* &t=k; //неверно...

Константный указатель или указатель на константу?
Привет всем.Уважаемые программисты пожалуйста скажите чем отличать когда написано например int...

Преобразование в указатель на указатель на константу
В упор не могу понять правила которые приводит Дьюхерст для преобразований "многоуровневых"...

Указатель на строковую константу
Здравствуйте уважаемые форумчане! Подскажите пожалуйста является ли эта ситуация выходом за...

16
Эксперт С++
1624 / 954 / 782
Регистрация: 06.02.2016
Сообщений: 2,452
Записей в блоге: 31
01.10.2016, 22:18 2
Потому что ival это целочисленная константа, а pi_ref3 указатель на целочисленную константу

Добавлено через 41 секунду
Юрий Ч, 2 вариант это КОНСТАНТНЫЙ УКАЗАТЕЛЬ на просто int

Добавлено через 17 секунд
1 вариант просто указатель на int
0
5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
01.10.2016, 22:32  [ТС] 3
Peoples, Хочу сказать, что всё-таки pi_ref0 - pi_ref3 - это не указатели, а ссылки на указатели. Но мне всё-таки не ясно, почему конструкция:

C++
1
const int* &pi_ref1 = &ival;
не является ссылкой на указатель на константу, ведь "const int*" - это как раз и есть указатель на константу?
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
01.10.2016, 23:03 4
Цитата Сообщение от Юрий Ч Посмотреть сообщение
Но мне всё-таки не ясно
Потому что выражение &ival порождает rvalue (в данном случае временный объект, типа "указатель на константу"), а (rvalue) временные объекты нельзя привязывать к lvalue ссылкам.
Можно использовать rvalue ссылку так:
C++
1
const int* &&pi_ref1 = &ival;
Либо const-ссылку (которая тоже позволяет привязывать временные объекты):
C++
1
const int* const &pi_ref1 = &ival;
Подробности и причины запрета в книге "Дизайн и эволюция С++", раздел про ссылки.
3
5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
02.10.2016, 00:12  [ТС] 5
DrOffset, Можно ещё вопрос.

C++
1
const int* &pi_ref1
- это ссылка на константный указатель или ссылка на указатель на константу?
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
02.10.2016, 00:21 6
То что до звёздочки - относится к данным по указателю, то что после - к самому указателю.
Значит:
Цитата Сообщение от Юрий Ч Посмотреть сообщение
ссылка на указатель на константу
0
Эксперт С++
3224 / 1751 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
02.10.2016, 00:25 7
Цитата Сообщение от nd2 Посмотреть сообщение
То что до звёздочки - относится к данным по указателю, то что после - к самому указателю.
Значит:
ссылка на указатель на константу
Просто читайте начиная от имени переменной влево, и оно само прочтется.
0
5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
02.10.2016, 00:31  [ТС] 8
Так, в общем,
C++
1
const int* &pi_ref1
- это ссылка на указатель на константу. Тогда мне снова не понятно почему компилятор не пропускает конструкцию:

C++
1
2
3
  const int ival = 1024;
 
  const int* &pi_ref1 = &ival;
ведь &ival - это же и есть указатель на константу? Или нет?
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
02.10.2016, 00:35 9
Цитата Сообщение от Юрий Ч Посмотреть сообщение
ведь &ival - это же и есть указатель на константу?
Да.
Но этот указатель - временный.
Значит к обычной ссылке не привяжется.
Я же уже написал об этом выше.
0
5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
02.10.2016, 00:45  [ТС] 10
DrOffset, Однако в книге Стенли Липпмана дана другая интерпретация, почему компилятор ругается на эти конструкции, а именно, цитирую:

Вот еще один пример ссылки, который трудно понять с первого раза. Мы хотим определить ссылку на адрес константного объекта, но наш первый вариант вызывает ошибку компиляции:

C++
1
2
3
const int ival = 1024;
// ошибка: нужна константная ссылка
int *&pi_ref = &ival;
Попытка исправить дело добавлением спецификатора const тоже не проходит:

C++
1
2
3
const int ival = 1024;
// все равно ошибка
const int *&pi_ref = &ival;
В чем причина? Внимательно прочитав определение, мы увидим, что pi_ref является ссылкой на константный указатель на объект типа int. А нам нужен неконстантный указатель на константный объект, поэтому правильной будет следующая запись:

C++
1
2
3
const int ival = 1024;
// правильно
int *const &piref = &ival;
Как видно, у Липпмана заработало
C++
1
int *const &piref = &ival;
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
02.10.2016, 00:48 11
Цитата Сообщение от Юрий Ч Посмотреть сообщение
Однако в книге Стенли Липпмана дана другая интерпретация
У него там, в примерах по этой теме, ошибки (опечатки, скорее всего) есть. Читаешь про const верхнего и нижнего уровня?
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
02.10.2016, 00:51 12
Цитата Сообщение от Юрий Ч Посмотреть сообщение
Однако в книге Стенли Липпмана дана другая интерпретация
Если там именно так и написано, то это конечно же ошибка.
Я могу допустить, что Липпман намеренно пока что не вдается в тонкости, но вот эта запись
C++
1
2
const int ival = 1024;
int *const &piref = &ival;
не будет скомпилирована ни одним компилятором, соответствующим стандарту. Поэтому что-то тут не то. Можно номер издания и страницу?
0
5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
02.10.2016, 00:52  [ТС] 13
nd2, Так кому верить? Книгу Липпмана считают чуть ли не библией для начинающего изучать С++, но при этом у него с первых страниц книги такие "опечатки". Перевёрнуто всё с ног на голову.
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
02.10.2016, 00:54 14
Опечатки везде бывают. Тут тем таких немало, сам возмущался недавно на Прату. Базовый курс читаешь?
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
02.10.2016, 00:57 15
Цитата Сообщение от Юрий Ч Посмотреть сообщение
Так кому верить?
Верить надо стандарту С++. (Да и то не всегда, там ведь тоже бывают ошибки, достаточно взглянуть на список defect reports).
Пока что лучше вот это почитать, чтобы усвоить тему: https://msdn.microsoft.com/ru-... 831hc.aspx
0
5 / 5 / 0
Регистрация: 16.05.2012
Сообщений: 178
02.10.2016, 00:58  [ТС] 16
DrOffset,
УДК 681.3.06
ББК 32.973.26-018.1
Л61

Липпман С - Язык программирования С++. Полное руководство. 3-е издание. Страница 118.
0
18829 / 9832 / 2403
Регистрация: 30.01.2014
Сообщений: 17,267
02.10.2016, 01:27 17
Лучший ответ Сообщение было отмечено hoggy как решение

Решение

Цитата Сообщение от Юрий Ч Посмотреть сообщение
Липпман С - Язык программирования С++. Полное руководство. 3-е издание.
Это издание очень старое.
Можно взять того же Липпмана, но поновее. Есть 5 издание, она и полнее и переведена, по-моему лучше.

В общем, посмотрел я этот раздел. Там выше он пишет о том же самом, о чем и я, о временных объектах и о невозможности привязать их к неконстантной lvalue-ссылке.
Цитата Сообщение от Из книги Липпмана
....
Для литералов это более или менее понятно: у нас не должно быть возможности косвенно поменять значение литерала, используя указатели или ссылки. Что касается объектов другого типа, то компилятор преобразует исходный объект в некоторый
вспомогательный. Например, если мы пишем:
C++
1
2
double dval = 102 4;
const int &ri = dval;
то компилятор преобразует это примерно так:
C++
1
2
int temp = dval;
const int &ri = temp;
Если бы мы могли присвоить новое значение ссылке ri , мы бы реально изменили не
dval, a temp. Значение dval осталось бы тем же, что совершенно неочевидно для программиста. Поэтому компилятор запрещает такие действия, и единственная возможность проинициализировать ссылку объектом другого типа — объявить ее как const.
....
А вот дальше начинается ерунда:
Цитата Сообщение от Из книги Липпмана
В чем причина? Внимательно прочитав определение, мы увидим, что pi_ref является ссылкой на константный указатель на объект типа int. А нам нужен неконстантный указатель на константный объект, поэтому правильной будет следующая
запись:
C++
1
2
3
const int ival = 1024;
// правильно
int *const &piref = &ival;
Тут получается, автор как бы противоречит сам себе.
В итоге я забрался в оригинал, и вот что я там увидел:
If we read this definition from right to left, we discover that pi_ref is a reference to a pointer to an object of type int defined to be const. Our reference isn't to a constant but rather to a nonconstant pointer that addresses a constant object. The correct definition is as follows:
C++
1
2
3
const int ival = 1024;
// ok: this is accepted
const int *const &pi_ref = &ival;
Кажется переводчик потерял разницу между ссылкой и указателем в этом месте, плюс подсократил оригинальную мысль автора, плюс добавилась опечатка, пропал const. Еще раз русская фраза, рядом с английской
А нам нужен неконстантный указатель на константный объект
Our reference isn't to a constant but rather to a nonconstant pointer that addresses a constant object
Делайте выводы сами.

Добавлено через 4 минуты
Так что все, о чем я выше написал, полностью совпадает с оригинальным Липпманом (за исключением rvalue-ссылок (&&), которых на момент написания книги просто не было в языке).

Добавлено через 2 минуты
Я даже сейчас склоняюсь к мысли, что переводчик не только не понял мысль автора, но и, решив, что он умнее, специально убрал первый const (исходя из неправильно понятного предложения), видимо подумал, что это в оригинальном тексте опечатка
1
02.10.2016, 01:27
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.10.2016, 01:27
Помогаю со студенческими работами здесь

Указатель на строковую константу
Всем привет. Я знаю что в С++ в основном юзается std::string,но сишные строки тоже желательно...

Ссылка на константу
Приветствую всех. Есть такой код: int fun() { return 777; } const int& i = fun(); Если i - это...

Инициализация ссылка на константу
Почему ссылку на константу можно инициализировать литералом? Ссылка же может быть связана только с...

Константный указатель на константу меняет значение
int d = 7; const int* const cd = &d; d = 8; qDebug()<<*cd;


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru