正在破坏函数返回的堆栈上的对象

Destructing objects on stack returned from funciton

本文关键字:堆栈 对象 返回 函数      更新时间:2023-10-16

下面的代码真的很危险吗?doSmth返回向量的对象,该对象应从contdoSmth)复制,然后存储在函数test范围内的堆栈中。因此,我相信只有从test返回后,它才会被拆除。

struct MyData
{
  double m_i;
};
std::vector<MyData> doSmth()
{
  std::vector<MyData> cont(10);
  return cont;
}
void test()
{
  MyData& oneElement = doSmth()[0];
  std::cout << oneElement.m_i << std::endl;
}

然而valgrind的想法不同:

Invalid read of size 8
<line 1 in test function oneElement>
Address 0x101281db8 is 8 bytes inside a block of size 72 free'd
std::vector<BlockInfo, std::allocator<BlockInfo> >::~vector() (stl_vector.h:314)
<line 2 in test function>

这是我逻辑上的问题还是残酷的谎言?

返回值在完整表达式的末尾销毁,即函数test中的第一个分号。在这一点上,oneElement变成了一个悬空参考。

您可以通过将返回值绑定到常量引用来延长其生存期:

void test()
{
    std::vector<MyData> const & r = doSmth();
    MyData const & oneElement = r[0];
    std::cout << oneElement.m_i << std::endl;
}

在上述情况下,返回值在函数结束时被销毁。

代码具有未定义的行为。doSmth的返回值是temporary,它在完整表达式的末尾被销毁。你对其调用operator[],返回对短暂的临时销毁后,参考挂起,任何对它的使用都是未定义的行为。

Valgrind抱怨是对的。