c++ - 带有 typeid 调用的 UB

标签 c++ undefined-behavior typeid

我已经编写了理解 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 说

If the operand of typeid refers to the object under construction or destruction and the static type of the operand is neither the constructor or destructor’s class nor one of its bases, the result of typeid is undefined

对吧?

最佳答案

我猜是UB。查看 C 的构造函数。

C()
    :            // 1
      B(this)    // 2
{                // 3
    ...

每个对象都应该有一些关于它的类型信息,所以我们可以猜测构造函数初始化它。

如您所知,标准为实现提供了很大的自由度。也许它没有决定构造函数是否应该在 //1//3 中初始化 typeinfo。如果一个实现决定在 //3 中初始化它,您会得到错误的结果,因为 typeinfo 没有在 //2 中初始化。


(但是,VC++ 2013 和 g++ 4.8.3 都给出了正确的结果。请注意 >o<)

我是对的。原因we could get correct resultC 没有虚函数。 如您所知,如果没有虚函数,则不会启用 RTTI。因此编译器从静态类型生成类型信息,即 C

使用虚函数,它生成 UB 的结果。

struct B
{
    long unsigned int hash;

    B(C *c);

    virtual ~B() = default; // here.
};

(live example)

关于c++ - 带有 typeid 调用的 UB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25581948/

相关文章:

c++ - C++标准算法中的ForwardIterator和OutputIterator能一样吗?

c++ - 查找模板参数的 typeid

c++ - typeid 是如何工作的,对象又是如何存储类信息的?

C++ - 区间树实现

c++ - 整数比较运算符是否在 C++ 中短路?

c++ - 向 snprintf 提供空指针时的预期行为

c++ - int(*g)(int) 转换为 int(*h)(char) 导致错误的原因?

c - 从函数和未定义行为返回局部部分初始化的结构

c++ - 表达式 (a=b) = k UB?

c++ - 有没有办法在变量中存储类型说明符?