Возвращение ссылки на данные из функции приводит к появлению проблем с ссылками - PullRequest
2 голосов
/ 22 июня 2011

Пожалуйста, проверьте два фрагмента кода ниже.В то время как в примере 2 явно присутствует проблема свисающих ссылок при передаче ссылки на локальную переменную, как вы думаете, такая же проблема существует в примере 1?Я сам считаю образец 1 правильным.Пока данные помещались в структуру данных (stl::queue), ссылка была взята (заголовок функции enqueue равен void enqueue(const int &data)).Поэтому здесь не должно быть проблем при возврате данных через &data.Или есть?

Образец 1:

int const& dequeue()
{
    _mutex.lock();
    int &data = _queue.back();
    _queue.pop();
    _mutex.unlock();
    return data;
}

Образец 2:

int const& dequeue()
{
    _mutex.lock();
    int data = _queue.back();
    _queue.pop();
    _mutex.unlock();
    return data;
}

1 Ответ

1 голос
/ 22 июня 2011

Неверный образец 1.

Ваша ссылка станет недействительной после того, как вы вызовете pop().

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

Это также означает, что образец 2 неверен, но не по той причине, о которой вы думаете.Да, возврат этой ссылки недопустим (она даже не должна компилироваться), но data недопустим до конца функции - опять же, сразу после вызова pop() все ссылки, которые у вас есть на объекты в этом контейнере, становятся недействительными.

Есть ли причина, по которой вы возвращаетесь по ссылке?Вы, очевидно, не ожидаете, что значение изменится вообще, и ваша ссылка const, так почему бы просто не вернуть значение?

int dequeue()
{
    _mutex.lock();
    int data = _queue.back();
    _queue.pop();
    _mutex.unlock();

    return data;
}

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

int glob;

int& f(){
  int x;
  int& ref = glob;
  return x;
}

int main(){
  foo()=10;  //this is fine
}
...