0

次のコードは本当に危険ですか?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>

それは私の論理または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[]と、テンポラリ内のデータへの参照が返されます。一時的な参照が破棄された後、参照はぶら下がり、それを使用すると未定義の動作になります。

ヴァルグリンドが文句を言うのは正しい。

于 2012-08-24T09:50:37.610 に答える