2014-08-30 3 views
1

Я написали код для понимания typeid оператор.UB с вызовом 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; 
} 

Я думаю, что код, который я написал производят UB в //1, потому что 12,7/5 говорит

Если операнд TypeID ссылается на объект незавершенного строительства или разрушения и статический тип операнд не является ни конструктор или деструктор класса, ни один из его баз, результат TypeID неопределен

Правильно?

+0

plz смотреть редактировать> o < – ikh

+0

(возможно) окончательное редактирование. plz see> o < – ikh

ответ

0

Я думаю, что это UB. Посмотрите на конструктор C.

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

Каждый объект должен иметь что-то о его типеinfo, поэтому мы можем предположить, что конструктор инициализирует его.

Как вы знаете, стандарт дает большую свободу для реализации. Возможно, он не решил, должен ли конструктор инициализировать typeinfo в // 1 или // 3. Если одна реализация решила инициализировать ее в // 3, вы получите неправильный результат, потому что typeinfo не инициализируется в // 2.


(Тем не менее, оба VC++ 2013 и г ++ 4.8.3 дают правильный результат. Обратите внимание на то, что> о <)

я был прав. Причиной we could get correct result является то, что C не имеет виртуальных функций. Как вы знаете, RTTI не включен, если нет виртуальных функций. Таким образом, компилятор генерирует типinfo из статического типа, который равен C.

С виртуальными функциями он генерирует результат UB.

struct B 
{ 
    long unsigned int hash; 

    B(C *c); 

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

(live example)

+1

Статический тип операнда - 'C'. Класс конструктора - 'B'. 'C' не является базой' B' –

+0

@MattMcNabb О, мой глаз, кажется, ввернул: (Позвольте мне подумать какое-то время – ikh

+0

@MattMcNabb (возможно) окончательное редактирование. Plz see> o < – ikh

0

Я не думаю, что это неопределенное поведение.

Предыдущее предложение говорит

Когда typeid используется в ... функция называется ... из конструктора ..., если операнд typedid ссылается на объект незавершенного строительства ... , typeid дает std::type_info, представляющий класс конструктора.

Соответствующий объект в стадии строительства c, и статический тип операнда typeid представляет собой С, так что результат является типом C.

Конструктор В также работает, но не c «объект под строительство» там, поэтому предложение, которое вы цитируете, не применяется.

+0

Но статический тип c (aka 'C') не является базой для' B'. Вы можете не понимать меня правильно. Я имею в виду, что UB создается во время построения 'C c;' и конструктор 'B' вызывается, когда' c' находится в разработке. –

+0

Полагаю, я тебя понимаю. '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''. –

+0

Я понял, что вы имеете в виду. Но что означает «объект в стадии строительства»? Я думаю, что это означает «после того, как строительство было начато, но срок жизни объекта по-прежнему не является». Поскольку конструктор B вызывается во время построения 'c', и это подразумевает, что мы применяем' typeid (c) 'к строимому объекту. Не могли бы вы указать мне, где я ошибаюсь по этой причине? –

Смежные вопросы