Glvalue是指基类子对象

时间:2014-09-07 09:35:34

标签: c++ lvalue

有一个限制:

  

同样,在对象的生命周期开始之前但在之后   对象占用的存储空间已被分配,或之后   对象的生命周期已经结束,在存储之前就已经存在了   对象占用被重用或释放,任何 glvalue引用   原始对象可能会被使用,但只能以有限的方式使用。对于一个对象   正在建设或破坏,见12.7。否则,这样的glvalue   指分配存储(3.7.4.2),并使用的属性   不依赖于其值的glvalue是明确定义的。该程序   在以下情况下具有未定义的行为:

     

[...]

     

- glvalue 绑定到对虚拟基类的引用(8.5.3),

     

[...]

如何将glvalue绑定到对虚拟基类的引用并同时引用原始对象?你能提供一个例子吗?

3 个答案:

答案 0 :(得分:1)

你正在读错那句话。您引用的项目符号的直接​​模拟,指向生命周期结束的对象的指针是(§3.8[basic.life] / p5):

  
      
  • 指针被隐式转换(4.10)为指向虚拟的指针   基类
  •   

所以它正在谈论这样的事情:

struct A { };
struct B : virtual A { ~B() {} };
int main() {
    B* pb = new B;
    B& rb = *pb;
    A& ra1 = rb; 

    pb->~B();    // ends lifetime of *pb
    &rb;         // OK
    A& ra2 = rb; // Undefined behavior. The glvalue rb, referring to an object whose lifetime
                 // has ended, is bound to a reference to its virtual base class A
    A* pa = pb;  // Equally undefined
}

答案 1 :(得分:1)

以下似乎是问题的证明:

struct Base {};
struct X : virtual Base {};

int main()
{
    X * p = static_cast<X *>(operator new(sizeof X));

    Base & r = *p;        // *p is an lvalue in the restricted sense
                          // binding it to a Base & has undefined behaviour

    operator delete(p);
}

答案 2 :(得分:1)

考虑对非平凡Derived对象的引用:使用显式析构函数调用销毁对象,并使用对该对象的引用来访问某些不使用/修改任何状态的函数( glvalue的属性,不依赖于它的值)。由于没有改变内存内容,这仍然是一个有效的操作(只执行了对象的清理)。

无论如何,如果glvalue在> 之前绑定到一个对象(生命周期初始化结束时开始),那么同样不是这样:如果你有一个Base&引用并且{{1这是一个虚拟类,它会有所不同:你将通过vtable调用方法/函数,但尚未初始化。未定义的行为。

e.g。

Base

A possible outcome from coliru