对匿名RVALUE的引用被损坏

Reference to anonymous rvalue is corrupted

本文关键字:引用 损坏 RVALUE      更新时间:2023-10-16

为什么以下代码...

#include <iostream>
#include <map>
template< typename T, typename U >
class Map
{
public:
  Map( const T& t, const U& u ) { map_[ t ] = u; }
  Map< T, U >& operator() ( const T& t, const U& u )
  {
    map_[ t ] = u;
    return *this;
  }
  U& operator[] ( const T& t) { return map_[ t ]; } 
private:
  std::map< T, U > map_;
};
Map< int, std::string >& g_map = Map< int, std::string> ( 1, "lorem" )
                                                        ( 3, "ipsum" )
                                                        ( 5, "dolor" );
int main( int argc, char* argv[] )
{
  std::cout << g_map[3] << std::endl;
  return 0;
}

...产生这种损坏的输出?...

>g++ -g main.cpp
>./a.out
ipsumÿÿÿÿlorem!h€Ap€AD€A!ˆ€A¼gì¿P€A€A,€A!p€A€AY

我最近了解到,分配对匿名rvalue的引用会延长rvalue对象的寿命。因此,我认为,由于匿名rvalue std::map是由全球范围g_map提到的,因此它的寿命将延长到全球范围变量的寿命,并且将使用g_map作为其他任何全球变量(如果不是的话(是有效的供参考,匿名rvalue将在结束的半隆上死亡(。

有人可以解释终身扩展规则如何适用上述?

用GCC 4.9.2。

进行的汇编

您本质上拥有这个:

class C {
public:
  C& detemporize() { return *this; }
};
C& cr = C().detemporize();

创建了一个临时C实例。然后在其上调用一种方法,该方法返回C&参考。编译器不知道也不关心回报值是指同一临时性的;虽然知道,它很可能会返回对某些全球,长寿的对象的引用。

无论如何,cr最终指的是那个临时性,然后立即死亡,而cr悬挂。随后使用它的任何尝试都表现出不确定的行为。

在您的代码中,Map::operator()扮演detemporize()的角色,使g_map悬挂参考。

我最近了解到,分配对匿名rvalue的参考会延长rvalue对象的寿命。

仅当您将临时对象直接分配给参考时才发生:

const obj &ref1 = obj(); // extends
const obj &ref = somefuncthatreturnsobj(); // extends

但是没有魔法,如果您调用一个函数,该函数以某种方式隐藏了引用它不再起作用:

class foo {
    const foo &get() const { return *this; };
};
const foo &ref1 = foo(); // extends lifetime of temporary
const foo &ref2 = foo().get(); // no lifetime extention, dangling reference