条件运算符+ upcast + const引用 [英] Conditional operator + upcast + const reference
问题描述
受到此问题的启发,我尝试了以下代码:
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&& static_cast< const A&>(C()));
a.doit()
}
我试过的每个编译器接受这个代码与 -Wall -Werror
并生成我想要的程序集。但是仔细阅读C ++ 03规范第12.2节(Temporaries)和第5.12节(条件运算符)后,我不确定这是否能保证工作。
那么,这是有效的代码,还是调用未定义的行为?对于C ++ 03和C ++ 11,答案是否不同?
相关规范的引用将不胜感激。
考虑:
<$> p $ p>
#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&
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 $ b〜B
〜A
纯虚拟方法称为
终止调用时没有活动异常
bash :line 7:16922 Aborted(core dumped)./a.out
这是UB所以任何解释都可以是真的,没有看到程序集,没有看到程序集,发生了什么:
- 构建了一个临时结构。
- 它绑定到引用。
这是绑定到引用的引用,因此不涉及创建新的临时或切片。 - 临时
- 作为其动态类型(vtable指针)的一部分,更改为
A
>
- 调用
A
中的纯虚拟。
Inspired by this question, I tried the following code:
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 accepts this code with -Wall -Werror
and generates the assembly I want. But after carefully reading the C++03 specification section 12.2 ("Temporaries") and section 5.12 ("Conditional Operator"), I am unsure whether this is guaranteed to work.
So, is this valid code, or does it invoke undefined behavior? Does the answer differ for C++03 and C++11?
Citations from relevant specifications would be appreciated.
Oh, it's very invalid.
Consider:
#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 );
}
Output in Coliru Viewer, using 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
It's UB so any explanation could be true, but one can be reasonably sure, without looking at the assembly, that what happens is:
- A temporary is constructed.
- It's bound to the reference.
This is a reference being bound to a reference, so does not involve creation of a new temporary or slice. - The temporary is destroyed.
- As part of that its dynamic type (vtable pointer) is changed to
A
, which is abstract. - The pure virtual in
A
is called.
这篇关于条件运算符+ upcast + const引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!