The reason these object addresses must be different if the types are the same, but the addresses can be the same if the types are different

We have empty base class optimization. Look at these two cases:

Case A

struct Empty1 { }; struct Empty2 { }; struct One: Empty1, Empty2 { }; 

Here sizeof(One) is 1. The addresses Empty1 and Empty2 same.

Case B

 struct Empty { }; struct Empty1: public Empty { }; struct Empty2: public Empty { }; struct Two: Empty1, Empty2 { }; 

Here, sizeof(Two) is 2. The addresses Empty1 and Empty2 are different from each other because they both have Empty (and these Empty must have different addresses).

Why does the standard allow you to have the same address for different types, but forbid for the same types? What problem does this rule avoid?

What problem will I have if I create a tuple implementation where all empty members will have the same address (regardless of their types)?

+5
source share
2 answers

The address is part of the object identifier. Separate objects of the same type having separate addresses are a general rule. This is how you know that there is more than one object.

In copy constructors, you can often find a test for self-assigning if (this != &other) . This will fail if different objects of the same type must have the same address.

Objects of different types cannot be compared, as it is in any case, therefore, not a problem. And we also have a structure and its first member and array and the first element, which have the same address but have different types.

An empty base class creates a problem here, but only if you have two base classes of the same type or the base class is of the same type as the first member of the derived class. Thus, there are special rules prohibiting the overlap of two identical objects in these cases.

The idea is that they should be two separate sub-objects and work in the test this != &that .

+3
source

The rule is specified in the standard [intro.object]:

If the object is not a bitfield or subobject of the base class with zero size, the address of this object is the address of the first byte that it occupies. Two objects a and b with overlapping lifetimes that are not bit fields can have the same address if it is nested in another, or if at least one is a subobject of the base class with zero size and they have different types; otherwise they have different addresses.

One of the reasons an empty base class falls into this rule is because you can apply a base class reference to a reference to a base object.

It’s best to see it in action, I added the assembly generated by gcc with -O3 optimization:

 struct Empty1 { }; struct Empty2 { }; struct One: Empty1, Empty2 { int i; }; struct Other{ int i; }; //an Empty and a One may have the same address int f(Empty1& a,One& b){ mov DWORD PTR [rsi], 12 //write to *rsi bi=12; mov DWORD PTR [rdi], 15 //may be rsi==rdi auto& a_one = mov eax, DWORD PTR [rsi] //reload from *rsi static_cast<One&>(a); ret a_one.i=15; return bi; } //an int and a One may have the same address int f(int& a,One& b){ mov DWORD PTR [rsi], 12 //write to *rsi bi=12; mov DWORD PTR [rdi], 15 //may be rsi==rdi a=15; mov eax, DWORD PTR [rsi] //reload from *rsi return bi; ret } //a long can not have the same address as a One int f(long& a,One& b){ mov DWORD PTR [rsi], 12 bi=12; mov eax, 12 //aliasing optimization a=15; mov QWORD PTR [rdi], 15 //sure rsi!=rdi aliasing rule return bi; ret } //the int inside and Other can alias an int inside a One int f(Other& a,One& b){ mov DWORD PTR [rsi], 12 bi=12; mov eax, 12 //aliasing optimization ai=15; mov QWORD PTR [rdi], 15 //sure rsi!=rdi aliasing rule return bi; ret } 

Only one complete object can exist at a given address. A complete object is one that is not nested in another.

It is not possible to succeed in an object at the same address (without UB) with the same type. But since you are an empty object, you do not need more than one in your optimized tuple. You will need to implement only get<I> , which refers to the same object for all Is intended to refer to an object of the same empty class.

+1
source

Source: https://habr.com/ru/post/1272011/


All Articles