0

下面的代码真的很危险吗?doSmth 返回 vector 的对象,该对象应该从cont( doSmth) 复制,然后存储在 function 范围内的堆栈中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>

这是我的逻辑问题还是 valgrind 谎言?

4

2 回答 2

4

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

您可以通过将返回值绑定到 const 引用来延长其生命周期:

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

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

于 2012-08-24T09:21:58.460 回答
2

代码具有未定义的行为。的返回值doSmth是一个临时值,它在完整表达式的末尾被破坏。您调用operator[]它,它会返回对临时内部数据的引用。临时销毁后,引用悬空,任何使用它都是未定义的行为。

Valgrind 的抱怨是对的。

于 2012-08-24T09:50:37.610 回答