我已经为理解typeid
运算符编写了代码。
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;
struct C;
struct B
{
long unsigned int hash;
B(C *c);
};
struct C : B
{
C() : B(this)
{
cout << "C()" << endl;
}
};
B::B(C *c)
{
hash = typeid(*c).hash_code(); //1, UB?
}
C c;
int main()
{
cout << c.hash << endl;
cout << typeid(c).hash_code() << endl;
}
我认为我编写的代码会在//1
生成UB,因为12.7 / 5表示
如果typeid的操作数指的是正在构造的对象或 破坏和操作数的静态类型都不是 构造函数或析构函数的类也不是它的基础之一 typeid未定义
右?
答案 0 :(得分:0)
我猜是UB。看看C
的构造函数。
C()
: // 1
B(this) // 2
{ // 3
...
每个对象应该有关于它的typeinfo的东西,所以我们可以猜测构造函数初始化它。
如您所知,标准为实现提供了很大的自由度。也许它没有决定构造函数是否应该在// 1
或// 3
中初始化typeinfo。如果一个实现决定在// 3
中初始化它,那么你会得到错误的结果,因为在// 2
中没有初始化typeinfo。
(但是,VC ++ 2013和g ++ 4.8.3都给出了正确的结果。请注意&gt; o&lt;)
我是对的。原因we could get correct result是 C
没有虚函数。如您所知,如果没有虚函数,则RTTI不会启用。因此编译器从静态类型生成了typeinfo,即C
。
使用虚函数,它会生成UB的结果。
struct B
{
long unsigned int hash;
B(C *c);
virtual ~B() = default; // here.
};
答案 1 :(得分:0)
我不认为这是不确定的行为。
上一句话说
在......中使用
typeid
来自构造函数的函数 ...,如果typedid
的操作数引用正在构造的对象...,typeid
产生代表构造函数类的std::type_info
。
正在构建的相关对象是c
,typeid
的操作数的静态类型是C,因此结果是C的类型。
B构造函数也在运行,但c
不是&#34;正在构建的对象&#34;那里,你所引用的句子不适用。