引用C++中函数返回的向量元素

use*_*028 7 c++ memory-management return reference return-by-value

有人可以验证以下是BUG,并解释原因吗?我想我知道,但我不清楚细节.(我的实际问题涉及枚举的向量,而不是整数,但我认为它不重要.)假设我有以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

我是否正确myIntRef立即是一个悬空引用,因为f的返回值在堆栈中无处保存?

此外,以下是有效的修复,还是它仍然是一个错误?

  const int myIntCopy = f()[0];  // copy, not a reference
Run Code Online (Sandbox Code Playgroud)

换句话说,是否可以复制第0个元素之前抛弃f()的返回结果?

Dav*_*eas 11

那是一个错误.在完整表达式结束时,const int &myIntRef = f()[0];将销毁临时向量并释放内存.以后任何使用myIntRef都是未定义的行为.

在某些情况下,绑定对临时的引用可以延长临时的生命周期.这不是这种情况之一,编译器不知道返回的引用std::vector<int>::operator[]是临时的一部分还是对int具有静态存储持续时间或任何其他事物的引用,并且它不会延长生命周期.


Lih*_*ihO 3

是的,这确实是错误的做法。你打电话时:

\n
return v;\n
Run Code Online (Sandbox Code Playgroud)\n

v正在创建对象的临时副本并且

\n
const int &myIntRef = f()[0];\n
Run Code Online (Sandbox Code Playgroud)\n

使用此临时副本的第一个元素初始化您的引用。在此行之后,临时副本不再存在,这意味着这myIntRef是一个无效的引用,使用它会产生未定义的行为

\n

你应该做的是:

\n
std::vector<int> myVector = f();\nconst int &myIntRef = myVector[0];\nstd::cout << myIntRef << std::endl;\n
Run Code Online (Sandbox Code Playgroud)\n

其中(感谢copy elision)使用赋值运算符myVector通过使用而不创建v副本来初始化对象。v在这种情况下,引用的生命周期等于myVector对象的生命周期,使其成为完全有效的代码。

\n
\n

关于你的第二个问题:

\n
\n

“另外,以下内容是有效的修复,还是仍然是一个错误?”

\n
 const int myIntCopy = f()[0];  // copy, not a reference\n
Run Code Online (Sandbox Code Playgroud)\n
\n

是的,这是另一种可能的解决方案。f()[0]将访问临时副本的第一个元素并使用其值来初始化myIntCopy变量。保证vby 返回的副本f()至少存在直到整个表达式执行完毕,请参见C++03 标准 12.2 临时对象 \xc2\xa73

\n
\n

临时对象在评估完整表达式 (1.9) 的最后一步被销毁,该完整表达式 (1.9)(在词法上)包含它们的创建点。

\n
\n