C ++中的“重新绑定”引用是否合法?

时间:2014-01-13 21:31:08

标签: c++ reference language-lawyer placement-new

C ++中的以下内容是否合法?

据我所知,Reference有一个简单的析构函数,所以它应该是合法的。
但我认为参考不能合法反弹......他们可以吗?

template<class T>
struct Reference
{
    T &r;
    Reference(T &r) : r(r) { }
};

int main()
{
    int x = 5, y = 6;
    Reference<int> r(x);
    new (&r) Reference<int>(y);
}

3 个答案:

答案 0 :(得分:18)

您没有重新绑定引用,您正在另一个具有新位置的内存中创建一个新对象。由于旧对象的析构函数从未运行过,我认为这将是未定义的行为。

答案 1 :(得分:11)

您的示例中没有引用反弹。第一个引用(在第二行构造,名称为r.r)在{Q}}生命周期内绑定到int表示的x。当第三行的放置新表达式重新使用其包含对象的存储时,此引用的生命周期结束。替换对象包含一个引用,该引用在其整个生命周期中绑定y,该引用将持续到其作用域的末尾 - main的结尾。

答案 2 :(得分:4)

我想我在下面的一段中找到了答案引用了一个关于琐碎的dtor / dtor副作用的文章,即[basic.life] / 7:

  

如果在对象的生命周期结束之后并且在重用或释放对象占用的存储之前,则在原始对象占用的存储位置创建新对象,指向原始对象的指针,引用原始对象的引用,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以   用于操纵新对象,如果:

     
      
  • 新对象的存储空间恰好覆盖原始对象占用的存储位置,

  •   
  • 新对象与原始对象的类型相同(忽略顶级cv限定符),

  •   
  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const限定或引用类型的非静态数据成员,并且

  •   
  • 原始对象是类型T的派生程度最高的对象,新对象是类型T的派生程度最高的对象(即,它们不是基类子对象)。 / p>

  •   

通过重用存储,我们结束了原始对象[basic.life] / 1

的生命周期
  

类型T的对象的生命周期在以下时间结束:

     
      
  • 如果T是具有非平凡析构函数的类类型,则析构函数调用将启动,或者

  •   
  • 重复使用或释放​​对象占用的存储空间。

  •   

所以我认为[basic.life] / 7涵盖了这种情况

Reference<int> r(x);
new (&r) Reference<int>(y);

我们结束由r表示的对象的生命周期,并在同一位置创建一个新对象。

由于Reference<int>是具有参考数据成员的类类型,因此[basic.life] / 7的要求。也就是说,r甚至可能不会引用新对象,我们也可能不会使用它来“操纵”这个新创建的对象(我将此“操作”解释为只读访问)。