0

It's my understanding a union's size is that of the largest member on that union. Does anyone know how a union behaves when a non-fixed size container such as a string is added to it? What is the size? Also, how does the size change when the new placement operation is used? Thanks!

Here is an example:

#include <string>
using namespace std;

class X {
public:
    union {
        int i;
        string s;
    };
    X(string ss) { new(&s) string{ss}; };
    ~X() { s.~string(); };
};

int main(int argc, char *argv[])
{
    X xx{"abc"};

    return 0;
}
Marci
  • 129
  • 1
  • 13
notaorb
  • 1,944
  • 1
  • 8
  • 18
  • 6
    `sizeof(std::string)` never changes. Also, see: https://stackoverflow.com/questions/40106941/is-a-union-members-destructor-called/40107282#40107282 – NathanOliver Jun 08 '20 at 16:47
  • Indeed, and you may be surprised to learn that `sizeof(std::string)` is always the same, whether the string is empty or holds the entire contents of all Harry Potter books. – Sam Varshavchik Jun 08 '20 at 16:50
  • Is that because the container string has some pointer to the string's actual data? – notaorb Jun 08 '20 at 16:51
  • 1
    Practically, yes. Same thing for `std::vector`, and all other containers. The size of all objects in C++ never changes. This is fundamental, and `std::string` manages all the memory, correctly, for you. Same thing for containers. This is why modern C++ code rarely needs to use `new` or `delete`. – Sam Varshavchik Jun 08 '20 at 16:52
  • In that case, does this code need to use the new placement operation on construction? – notaorb Jun 08 '20 at 16:53
  • 1
    Yes, it does. When a union contains non-PODs, you are responsible for correctly constructing and destroying union members, one at a time, and in order. But way force this headache upon yourself? Just use `std::variant` and it, too, will do all of this for you. – Sam Varshavchik Jun 08 '20 at 16:55
  • I strongly recommend Sam's suggest. `union` is easy to get wrong, hard to get right, and can easily cause a work-late-weekend. `std::variant` is easy to get right, hard to get wrong, and can save you a lost weekend. Unless you're optimizing for job security. – Eljay Jun 08 '20 at 16:59
  • Thanks, I'm simply following Stroustrups C++ 4th Ed, around page 200. So if `string` was declared in the class body, the new placement operation would NOT be required correct? – notaorb Jun 08 '20 at 17:02
  • Correct. The only reason you need placement `new` here is the `union`. If you don't have to share storage between the `int` and the `string`, your life becomes whole orders of magnitude easier. – user4581301 Jun 08 '20 at 17:06

2 Answers2

3

It's my understanding a union's size is that of largest member on that union.

Not quite exactly. If one member has stricter alignment requirement, and another member is larger, but not a multiple of the mentioned alignment, then the total size of the union may be larger than either member.

Does anyone know how a union behaves when a non fixed size container

There are no non-fixed size types in C++. All types have a compile time constant size. Dynamic containers allocate memory from the free store, and indirectly refer to that memory with constant sized pointers.

What is the size?

It is exactly sizeof(X) bytes.

Also, how does the size change when the new placement operation is used?

It does not change.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

sizeof(std::string) is always the same, whether the string is empty or holds a string. The only reason the new placement operator is required is because of the string existing in the union, because storage is shared between the string and the int.

notaorb
  • 1,944
  • 1
  • 8
  • 18