Does the C++17 standard guarantee that the address of a union is the same as the address of its members?
Asked Answered
T

2

10

I am currently working on programming a pool allocator. My question boils down to the following code:

template <typename T>
union myUnion {
    T data;
    myUnion<T>* nextUnion;
};

void someFunction(){
    myUnion<T> mu;
    T* t = new (std::addressof(mu.data)) T();
    //some code
    myUnion<T>* mu2 = reinterpret_cast<myUnion<T>*>(t);
}

Is the address of mu always the same as mu2?

Trilley answered 2/5, 2017 at 21:24 Comment(7)
Which standard?Paulino
What would be the point of the union otherwise?Magistral
@MadPhysicist: Almost everything else about it.Paulino
@MadPhysicist The standard specifies that " unions ... are classes capable of containing objects of different types at different times". That's their point.Ula
Whatever the standard says, T* t = new (std::addressof(mu.data)) T(); is probably not a good idea if there is any non-trivial constructor or destructor involved.Ula
@n.1.8e9-where's-my-sharem. Why? T inside the Union is unconstructed during the union creation and thus any constructor call should work. Calling the destructor properly afterwards when the element is given back to the allocator should also be valid. Am I missing something?Trilley
@Trilley sorry my bad, if there are constructors or destructors of T involved you just need to provide the same for myUnion .Ula
S
19

Yes.

9.2/19 (12.2/24 in N4659):

If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member.

If the union itself is standard-layout, then the address of the union is the same as its members'.

The addresses of the members are all the same, thanks to 9.5/1 (12.3/2 in N4659):

Each non-static data member is allocated as if it were the sole member of a struct. All non-static data members of a union object have the same address.

Stadler answered 2/5, 2017 at 21:41 Comment(16)
Isn't this §9.2/20 in C++11/C++14?Notate
@Cameron: There is no 9.2/20 in C++14.Paulino
It's 9.2/19 in the draft I have. Don't have the actual standard, it's too expensive.Stadler
@Fanael: Please refer to standards, not drafts. (Having said that, I agree with this answer)Paulino
Weird, it's 9.2/20 in the one I have (N4296).Notate
@Cameron: Then that is not C++14.Paulino
@BoundaryImposition: I will, if you give me 200 CHF. That said, it'd be useless: the content of N4140 is identical to the actual standard.Stadler
@Cameron: but there's no 9.2/19 in my copy of N4140.Stadler
Ah, just realized I was reading the "revises" field. I actually have N4296.Notate
Probably more relevant is "9.5/1 Unions ... Each non-static data member is allocated as if it were the sole member of a struct. All non-static data members of a union object have the same address." See this answer: https://mcmap.net/q/1002564/-is-it-legal-to-use-address-of-one-field-of-a-union-to-access-another-field Just find the reference that says what the address of the first element of a struct is.Glyptograph
Both passages are pertinent, surely.Notate
@Notate Both answers are pertinent, but if T isn’t standard-layout, then the union won’t be either.Revolutionize
@Fanael N4140 isn't actually the same as the standard; it's got a lot more editorial fixes. N4141 is the C++14 IS.Flabby
@Flabby Fair point, but I wouldn't exactly say "a lot more". The differences are pretty minor, and none apply to the quoted passages.Stadler
@Fanael The current version of your answer doesn’t say that it works for non–standard layout T (which allocators often need to deal with). I think struct layout guarantees that it works, though.Revolutionize
The clauses about pointer-interconvertible would improve this answer. Ie, what does "same address" mean as far as the standard is concerned.Fielding
U
1

It is not enough to ask if two objects have the same address. For instance, an array and its first element are guaranteed to have the same address, but you cannot cast one to the other.

Fortunately, union and its members are guaranteed to be pointer-interconvertible, regardless of whether any of them is standard layout.

Ula answered 2/8, 2021 at 13:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.