从函数返回的堆栈上的解构对象

时间:2012-08-24 09:18:52

标签: c++ valgrind

以下代码真的很危险吗? doSmth返回vector的对象,该对象应从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>

这是我的逻辑或valgrind谎言中的问题吗?

2 个答案:

答案 0 :(得分:4)

返回值在完整表达式结束时被销毁,即在函数test的第一个分号处被销毁。此时,oneElement成为悬空参考。

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

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

在上面的例子中,返回值在函数结束时被销毁。

答案 1 :(得分:2)

代码具有未定义的行为。 doSmth的返回值为a 临时的,在完整表达结束时被破坏。您 在其上调用operator[],它返回对数据内部的数据的引用 临时。破坏后的临时,参考 悬挂,任何使用都是不确定的行为。

Valgrind抱怨是对的。