条件运算符+ upcast + const引用

时间:2014-04-14 00:05:57

标签: c++ c++11 language-lawyer

this question的启发,我尝试了以下代码:

struct A {
  virtual void doit() const = 0;
};

struct B : public A {
  virtual void doit() const;
};

struct C : public A {
  virtual void doit() const;
};

void
foo(bool p)
{
  const A &a = (p ? static_cast<const A &>(B()) : static_cast<const A &>(C()));
  a.doit();
}

Every compiler I have tried接受此代码-Wall -Werror并生成我想要的程序集。但仔细阅读C ++ 03规范第12.2节(&#34; Temporaries&#34;)和第5.12节(&#34;条件运算符&#34;)后,我不确定这是否可以保证有效。

那么,这是有效的代码,还是调用未定义的行为?对于C ++ 03和C ++ 11,答案是否有所不同?

相关规范的引文将不胜感激。

1 个答案:

答案 0 :(得分:6)

哦,这是非常无效的。

考虑:

#include <iostream>
using namespace std;

struct A {
    virtual ~A() { cout << "~A" << endl; }
    virtual void doit() const = 0;
};

struct B : public A
{
    ~B() override { cout << "~B" << endl; }
    void doit() const override { cout << "A::doit" << endl; }
};

struct C : public A
{
    ~C() override { cout << "~C" << endl; }
    virtual void doit() const { cout << "C::doit" << endl; }
};

void foo(bool p)
{
    cout << "foo( " << p << ")" << endl;
    const A &a = (p ? static_cast<const A &>(B()) : static_cast<const A &>(C()));
    a.doit();
}

auto main( int argc, char* argv[] ) -> int
{
    cout << boolalpha;

    foo( true );
    cout << endl;
    foo( false );
}

Coliru Viewer中的输出,使用g ++ 4.8:

foo( true)

~B

~A

pure virtual method called

terminate called without an active exception

bash: line 7: 16922 Aborted                 (core dumped) ./a.out

这是UB,所以任何解释都可能是真的,但是可以合理地确定,不看议会,发生的事情是:

  • 构建临时。
  • 这与参考书有关 这是一个绑定到引用的引用,因此不涉及创建新的临时或切片。
  • 临时被毁。
  • 作为其中一部分,其动态类型(vtable指针)更改为A,这是抽象的。
  • 调用A中的纯虚拟内容。