Is a compiler allowed to omit a reference member in a class?

10

Consider the following class:

struct Type {
    int a, b, c;
    int& ref;
    Type(int m) : a(m), b(m), c(m), ref(a) { }
    Type(const Type& ot) : a(ot.a), b(ot.b), c(ot.c), ref(a) { }
} obj;

Here we have that sizeof(Type) is 24 . However, obj.ref can always and in any situation / context be replaced with obj.a , causing the reference to be resolved at compile time and making useless save the 8 bytes of the reference in the object (and the 4 of padding). Ideally% w / w% can be w / w% (only w / w% w).

Can a compiler perform this optimization while strictly following the rules of the standard? Because? Is there any situation where this optimization would be incorrect?

Demonstrate with an example that produces different behavior with / without optimization.

    
asked by anonymous 20.02.2014 / 18:00

4 answers

4

First, the standard states the following in section 8.3.2, paragraph 4:

  

It is unspecified whether or not a reference is required.

Then a compiler is free to omit the allocation of a reference whenever this does not change the behavior of the program. The size of the object can be 12 .

In the case of the question, the optimization will be valid if and only if the compiler can prove that obj.ref always results in obj.a , ie any construction of a reference in obj.ref will be done so that it "points" to obj.a .

References receive an object at startup and can not be changed until destruction. If a reference is a member, then its life is equal to the life of the object that contains it, so the only place where it is legal to initialize a reference is at the initialization of the object, this occurs in the builder's initialization list.

If the compiler can see all constructors in the class definition and if all they initialize the reference in the same way (for a member of the object itself), then it does not exist as the reference at any time refer to another object. optimization is valid for the example question.

    
20.02.2014 / 21:53
2

Your case is was a problematic situation:

#include <iostream>

struct Type {
    int a, b, c;
    int& ref;
    Type(int m) : a(m), b(m), c(m), ref(a) { }
};

int main() {
    Type a(42);
    Type b(a);

    std::cout << &a.ref << "  " << &b.ref << std::endl;
    std::cout << &a.a << "  " << &b.a << std::endl;
}

0xbfb1efa0  0xbfb1efa0
0xbfb1efa0  0xbfb1efb0

link

How can the compiler with sufficient intelligence ensure that such an optimization would cause the behavior to not change (between reference implementation via pointers or by its omission) for this example and other possible cases?

More info on possible referral optimizations at: link

    
20.02.2014 / 20:46
0

A subclass of Type can overwrite the constructor and initialize ref differently. This would invalidate this optimization.

    
20.02.2014 / 18:35
0

I see problem if two different compilation units (two .cpp files) used this struct (via definition in a .h file, for example), and in one of them the compilation was with optimization and in the other one without optimizations . It would be impossible to link the object files generated by the two drives later.

In this way, something like this should be a forbidden or always mandatory optimization, since if it were optional (and configurable, like other optimizations), it would make it impossible to build a separate compile model of language binding.

    
21.02.2014 / 17:36