управление памятью — ссылка на элемент вектора, возвращаемый функцией в переполнении стека

Может ли кто-то проверить, что следующее является ошибкой, и объяснить, почему? Я думаю, что знаю, но неясно о деталях. (Моя настоящая проблема связана с вектором перечислений, а не целых чисел, но я не думаю, что это должно иметь значение.) Предположим, у меня есть следующий код:

std::vector<int> f (void) {
std::vector<int> v;
v.push_back(5);
return v;
}

void g (void) {
const int &myIntRef = f()[0];
std::cout << myIntRef << std::endl;
}

Правильно ли я утверждаю, что myIntRef — это непосредственно свисающая ссылка, потому что возвращаемое значение f нигде не сохраняется в стеке?

Кроме того, является ли следующее исправление корректным или это все еще ошибка?

  const int myIntCopy = f()[0];  // copy, not a reference

Другими словами, отбрасывается ли результат возврата функции f () до того, как 0-й элемент может быть скопирован?

7

Решение

Да, это действительно неправильно. Когда вы звоните:

return v;

временная копия объекта v создается и

const int &myIntRef = f()[0];

инициализирует вашу ссылку первым элементом этой временной копии. После этой строки временная копия больше не существует, а это означает, что myIntRef является недействительной ссылкой, использование которой приводит к неопределенное поведение.

Что вы должны сделать, это:

std::vector<int> myVector = f();
const int &myIntRef = myVector[0];
std::cout << myIntRef << std::endl;

который (благодаря копия elision) использует оператор присваивания для инициализации myVector объект с помощью v без копии v создается В этом случае время жизни вашей ссылки равно времени жизни myVector объект, что делает его совершенно корректным кодом.


И на ваш второй вопрос:

«Кроме того, является ли следующее исправление корректным, или это все еще ошибка?»

 const int myIntCopy = f()[0];  // copy, not a reference

Да, это еще одно возможное решение. f()[0] получит доступ к первому элементу временной копии и использует его значение для инициализации myIntCopy переменная. Гарантируется, что копия v вернулся f() существует по крайней мере, пока не будет выполнено все выражение, см. Стандарт C ++ 03 12.2 Временные объекты §3:

Временные объекты уничтожаются как последний шаг в оценке полного выражения (1.9), которое (лексически) содержит точку, где они были созданы.

2

Другие решения

Это ошибка. В конце полного выражения const int &myIntRef = f()[0]; временный вектор будет уничтожен, а память освобождена. Любое последующее использование myIntRef является неопределенным поведением.

При некоторых обстоятельствах привязка ссылки к временному может увеличить срок действия временного. Это не один из таких случаев, компилятор не знает, была ли ссылка возвращена std::vector<int>::operator[] является частью временного или ссылки на int со статической продолжительностью хранения или любой другой вещью, и это не продлит срок службы.

11

По вопросам рекламы [email protected]