Не понимаю тонкость при работе с ссылкой на константу в функции С++

int& F(const int& a) {return a;}

Решал задачу: по словарю и ключу (существующему) нужно вернуть ссылку на значение. Встал вопрос, почему не работает данный код (компилятор выбрасывает не warning, а ошибку: binding reference of type 'int&' to 'const int' discards qualifiers) Из ошибки ясно, что он не может преобразовать константу в ссылку. Если передавать простую ссылку в F, то код работает как надо Вопрос к вам: можно ли передать ссылку на константу (чтобы не бояться за повреждение данных внутри функции), при этом возвращая адрес как результат?


Ответы (4 шт):

Автор решения: Стass

Можно так:

const int& F(const int& a) {return a;}

Или с указателями:

const int* F(const int* a) {return a;}
→ Ссылка
Автор решения: Harry

Cмотрите, пусть ваш код разрешен и компилируется. Что тогда получается? например, получается можно написать

F(5) = 3;

что попросту бред... или

const int x = 5;
F(x) = 8;

и все, вся константность x оказывается нарушена.

Поэтому так делать нельзя. Проблема не в "повреждении данных в функции", а в возможном повреждении данных вне ее.

Тут уж решайте сами - или и передавайте, и возвращайте константную ссылку, или неконстантную...

Конечно, есть еще вариант

int& F(const int& a)
{
    return const_cast<int&>(a);
}

но я бы не рекомендовал им пользоваться. Можно получить неприятностей...

→ Ссылка
Автор решения: AR Hovsepyan

Константная ссылка предназначена только для чтения, то есть не возможно посредством этой ссылки изменить состояние объекта. Если вы присваиваете ее не константной ссылке(возвращением из функции), то вы связываете эти имена:

 const int& a = b; 
 //посредством `а` нельзя изменить состояние `b` 
 int& c = a;   
 // посредством с можно изменить состояние `b` 

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

Наоборот, если первая ссылка не константная, а вторая константная:

 int& a = b;  
 const  int& c = a; 

то это вполне нормальное определение. Одна ссылка для чтения и записи, а вторая только для чтения.

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

→ Ссылка
Автор решения: AlexGlebe

Функции с аргументами как ссылка на константный объект принимают даже временные объекты, время жизни которых заканчиваются после возвращения из функции. Можно убрать вручную константность ссылки, это разрешается. Но следует запретить временные аргументы или использовать аргумент не как ссылку, а указатель. Дело в том,что брать указатель у временных объектов нельзя. Вот эти примеры, написаны в стандарте c++11. Если нужен c++98, то останется использовать только аргумент как адрес.

// g++-9 -Wall -std=c++11 constarg.cpp
int& F(const int& a) {
  return const_cast<int&>(a); }

// запрет на временные аргументы у которых
// нежелательно использовать их адрес в дальнейшем.
// Пусть даже они константные.
int& F(const int && a) = delete ;

// аргумент как указатель не будет
// принимать адрес временных объектов
int & Fp(const int * const a) {
  return const_cast<int&>(*a); }

int main(){
  // переменная в стеке
  int i = 1 ;

  // ссылка на переменную i
  int & i1 = F(i);

  // ссылка на мусор в памяти
  // error: use of deleted function ‘int& F(const int&&)’
  // int & it  = F(10);

  // ссылка на переменную i
  int & ip1 = Fp(&i);

  // ссылка на мусор в памяти
  // error: lvalue required as unary ‘&’ operand
  // int & ipt  = Fp(&10);

  }
→ Ссылка