@Whiteha

Валидно ли передавать ссылку по ссылке в C++?

1) Не содержит ли такой код UB?
2) Может ли функция принимающая объект по ссылке передать его другой функцие по ссылке?
3) А если обе функции inline?
4) Есть ли разница в этом вопросе (без шаблонов) между C++03 и C++11?
#include <iostream>
using namespace std;
void b (int &j)
{
	j = 42;
}
void f (int &i)
{
	i = -1;
	b(i);
}
int main() 
{
	int i = 0;
	f(i);
	cout << i << endl;
}


ideone.com/IGDfRz

PS В стандарте на вскидку не нашел про это, хотя там в 8.3.2.5 есть запрет на существование "ссылок на ссылки".
  • Вопрос задан
  • 243 просмотра
Решения вопроса 2
Nipheris
@Nipheris Куратор тега C++
> ссылок на ссылки
Это не ссылка на ссылку. В функцию b попадет точно такая же ссылка, что и в f. Ссылки ведут себя как "вторые имена" для переменных, поэтому когда вы инициализируете одну ссылку другой, вы просто добавляете в распоряжение еще одно имя для куска памяти. Такого понятия, как ссылка на ссылку в принципе быть не может, в отличие от "указатель на указатель", т.к. указатель сам по себе - реальная самостоятельная переменная с выделенной для нее памятью, на которую, в свою очередь, также можно получить указатель. Ссылка - это запись в таблице идентификаторов компилятора. Да, в зависимости от ситуации для обеспечения ее работы может потребоваться указатель (например, при передаче ссылки в функцию нужно как-то передавать адрес), но этим уже занимается компилятор, поддерживая для вас абстракцию ссылки.
Другое дело - это, как указал Александр Ручкин - время жизни объекта, это другая история. Разумеется, тот объект или значение, ссылку на который мы сформировали, должны "жить", пока к этому объекту идут какие-либо обращения на чтение/запись.
UPD: Кстати, int&& - это НЕ ссылка на ссылку, это r-value ссылка и совсем другая история.
Ответ написан
Комментировать
1. UB нет
2. Может
3. inline не влияет
4. Насколько я знаю, нет

Запрет существования ссылок на ссылки - это отсутствие типа (T &) &. Сравни с указателем: тип (T *) * вполне допустим.

Проблема со ссылками может быть, если объект, на который ссылаются, помирает раньше, чем ссылка, например
struct foo { foo(int const & x) : x_(x) {}; int const & x_; };

int bar() { return 42; }
void baz() { foo f(bar()); ... } // здесь в foo передается ссылка на временный объект, который умирает в конце выражения, однако ссылка сохраняется в объекте f.


Или проще
struct foo { foo(int & x) : x_(x) {}; int & x_; };

void foo()
{
  std::shared_ptr<foo> f;
  {
    int x;
    f.reset(new foo(x));
  } // тут x помирает, ссылка на него невалидна
  f->x_ = 10; // UB
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@dmitryKovalskiy
программист средней руки
1) За каждую переменную i,b,j,f - шарахните себя клавиатурой по пальцам.
2) Если код скомпилился и работает в runtime встает другой вопрос. Вы путаете "можно" и "нужно". С++ позволяет зверские шаманства с указателями, но это не значит что код получается хороший. Поддержка и развитие такого кода тоже имеет значение.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы