Home > Blockchain >  Diffrence between frequently use of typeid?
Diffrence between frequently use of typeid?

Time:03-24

What's difference between these codes and why do I have a warning in the second code?

warning: expression with side effects has no effect in an unevaluated context


struct A
{ };
struct B : A
{ };  
int main(){ 
    A* temp = new A();
    A* temp1 = new B();
    std::cout << "B==A : " << (typeid(temp1) == typeid(temp)) << std::endl; 
    return 0;
}
    // ..  above code changed just one line:
    std::cout << "B==A : " << (typeid(temp1) == typeid(new A())) << std::endl;

I would also like some explain about the warning?

CodePudding user response:

There is no point in writing typeid(new A()). It is just a more complicated way of writing typeid(A*).

But typeid(new A()) may look as if it will create a new A object and call its constructor. The expression is however evaluated only if it is a glvalue of polymorphic type, which it isn't here. It is difficult to quickly recognize whether or not the expression is a glvalue of polymorphic type and therefore the compiler may warn you in either case about it if the expression would have side effects. (At least that seems to be what GCC does.)

Furthermore typeid(temp1) == typeid(temp) is also pointless. This simply compares the declared types of the two variables since they are pointer types and will always result in true, because both temp1 and temp are of type A*.

Maybe you meant to do typeid(*temp1) == typeid(*temp). But that will also always result in true here, since A is not a polymorphic type. (It doesn't have any virtual functions.)

CodePudding user response:

Without going into the full description of what constitutes a glvalue expression, it is clear from your code that A is not a polymorphic class; so, for the purposes of the excerpt below, the expression new A() is clearly not, "a glvalue of a polymorphic class type."

Thus, from this Draft C Standard, we can see that that expression will not be evaluated (bold emphasis mine):

8.5.1.8 Type identification      [expr.typeid]


3     When typeid is applied to an expression other than a glvalue of a polymorphic class type, the result refers to a std::type_info object representing the static type of the expression. Lvalue-to-rvalue (7.1), array-to-pointer (7.2), and function-to-pointer (7.3) conversions are not applied to the expression. If the expression is a prvalue, the temporary materialization conversion (7.4) is applied. The expression is an unevaluated operand (8.2).

The compiler is warning you that the new A() expression will not be evaluated. This may not seem important, in the code that you have shown, but may become relevant if your A constructor does something that changes the running environment, like modifying a static class member: For example, add a static int count variable to A, initialized to zero, and increment that in the A constructor; printing the value of that counter at the end of the main illustrates the issue:

#include <iostream>

struct A {
    static int count;
    A() {   count; }
};
struct B : A {
};

int A::count{ 0 };

int main()
{
    std::cout << A::count << std::endl; // 0
    A* temp1 = new B(); // Calls A c'tor: count now 1
    std::cout << A::count << std::endl; // 1
    std::cout << "B==A : " << (typeid(temp1) == typeid(new A())) << std::endl; // No c'tor call!
    std::cout << A::count << std::endl; // count STILL 1
    return 0;
}
  • Related