URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7690
[ Назад ]

Исходное сообщение
"Ссылки, константы, указалели... тонкий момент"

Отправлено Ivanoff , 07-Ноя-08 10:12 
Доброго времени суток, помогите разобраться с константами, указателями и ссылками:
const int cint = 5; // Целочисленная константа
const int *pcint = 0; // Указатель на целочисленную константу
int *const cpint=0; // Константный указатель на целочисленную константу
const int &refInt = 7; // Ссылка на константу
const int *&refInt = &cint; // а вот тут не работает, почему ???
Ведь const int *&refInt - ссылка на указатель на целочисленную константу?
В Липпмане написано что надо делать не так:
const int *&refInt = &cint;
а вот так:
int *const &refInt = &cint;
Но ведь позвольте :) int  *const &refInt - это ссылка на Константный указатель, а значит он точно не к селу не к городу, да и во вторых вариант Липпмана тоже не компилируется :)

Содержание

Сообщения в этом обсуждении
"Ссылки, константы, указалели... тонкий момент"
Отправлено jd2 , 07-Ноя-08 14:35 
>const int cint = 5; // Целочисленная константа
>const int *&refInt = &cint; // а вот тут не работает, почему

Надеюсь, это у Вас хотя бы аргументы функции, а не автоматические переменные таких чуднЫх типов... :)
Ближе к делу: компилятор ведь обычно не говорит просто, "ну не шмагла", он обычно говорит, в чём именно проблема. С данным примером я получил:

error: invalid initialization of non-const reference of type 'const int*&' from a temporary of type 'const int*'

Из чего несложно понять, что нужно делать так:

const int* const& refcpint = &cint;

А вообще, когда я вижу что-то подобное, у меня возникает стойкое ощущение, что с кодом что-то не так. То есть, IMHO не всё, что позволяется синтаксисом языка, есть хорошо.


"Ссылки, константы, указалели... тонкий момент"
Отправлено Ivanoff , 09-Ноя-08 12:23 
>Надеюсь, это у Вас хотя бы аргументы функции, а не автоматические переменные
>таких чуднЫх типов... :)

это вообще не код, в смысле взят просто из учебника липмана

>[оверквотинг удален]
>он обычно говорит, в чём именно проблема. С данным примером я
>получил:
>
>error: invalid initialization of non-const reference of type 'const int*&' from a
>temporary of type 'const int*'
>
>Из чего несложно понять, что нужно делать так:
>
>

const int* const& refcpint = &cint;

>

Вот... поясните как читается const int* const& refcpint это константная ссылка на указатель на константу целого типа или же это ссылка на константный указатель на константу целого типа? и почему не подходит мой вариант, а точнее вариант липпмана?


"Ссылки, константы, указалели... тонкий момент"
Отправлено jd2 , 14-Ноя-08 01:12 
Ну, честно говоря, как это правильно произносится, я не задумывался - не вижу смысла в подобных упражнениях. А по поводу, почему так правильно, а так нет...

Итак, что мы имеем в вашем варианте (упростим немного для ясности):

int i = 5;
int* & refi = &i;

На что справедливо получаем:

test.cc:3: error: invalid initialization of non-const reference of type 'int*&' from a temporary of type 'int*'

А справедливо потому, что мы пытаемся инициализировать ссылку на несуществующий указатель. В том смысле, что переменной, содержащей указатель на int, на которую будет ссылаться наша ссылка, не существует. Компилятор создаёт в этом месте временную (?) переменную. Забыл, как это правильно называется - это примерно то же самое, что при возвращении значения из функции или при приведении типов в выражении. Второй вариант встречается, например, в случае такого кода:

int i;
double x;
... = i + x;

Здесь перед выполнением операции сложения, создаётся временная переменная типа double, в которую помещается приведённое к double значение i, а уже потом она складывается с x, после чего сразу уничтожается.

Так вот, то же самое происходит и в вашем случае! Ссылка должна ссылаться на переменную (константу), а соответствующей переменной (константы) не существует, поэтому компилятор создаёт временную. А так как в концепции C++ нет такого понятия, как автоматическая сборка мусора, то переменная должна быть явно уничтожена - либо после операции, в которой она используется (как в примере выше), либо когда закончится область видимости ссылки на эту временную переменную. Разумеется, "когда" здесь означает не время, а место.

А константной (!) ссылка должна быть потому, что будь она не константной, она могла бы в любой момент начать ссылаться на что-нибудь другое (простым присваиванием) и тогда наша временная переменная потерялась бы где-то в памяти, так как стало бы совершенно непонятно, когда её уничтожать (ведь сборки мусора в C++, как я уже говорил, нет). Фуф, примерно так. Путанно объяснил, потому как чукча не писатель... Точнее, писатель, но другого рода.

А вообще, лучше Страуструпа почитать. Всё-таки лучше источника информации по C++ нет.