Может ли кто-то проверить, что следующее является ошибкой, и объяснить, почему? Я думаю, что знаю, но неясно о деталях. (Моя настоящая проблема связана с вектором перечислений, а не целых чисел, но я не думаю, что это должно иметь значение.) Предположим, у меня есть следующий код:
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-й элемент может быть скопирован?
Да, это действительно неправильно. Когда вы звоните:
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), которое (лексически) содержит точку, где они были созданы.
Это ошибка. В конце полного выражения const int &myIntRef = f()[0];
временный вектор будет уничтожен, а память освобождена. Любое последующее использование myIntRef
является неопределенным поведением.
При некоторых обстоятельствах привязка ссылки к временному может увеличить срок действия временного. Это не один из таких случаев, компилятор не знает, была ли ссылка возвращена std::vector<int>::operator[]
является частью временного или ссылки на int
со статической продолжительностью хранения или любой другой вещью, и это не продлит срок службы.