1

I am fiddling with a code like following:

union Data { 
    int i;
    double x;
    std::string str;
    ~Data(){}
};

union Data var = {.x = 31293.932};

std::cout << var.x << "\n";
std::cout << var.str << "\n";
std::cout << var.i << "\n";

As far as I know, the union have some 64 bit thing written after I set x member to some floating point number. Then I want to see corresponding string, asuming I treated those bytes as char. But I am getting segmentation fault when I try to print it as string. Why is that? I initialized the union so I assume var.str must be initialized as well.

meguli
  • 1,426
  • 1
  • 18
  • 35
  • 2
    Basically, throwing a bunch of bytes into a memory slot and hoping that you can treat those bytes as a valid `std::string` object is a recipe for disaster. – Sam Estep Feb 11 '16 at 19:27
  • 3
    You're expecting putting the members into the union magically enables them to convert from any data type to any other data type, and that's not how things work. – Ken White Feb 11 '16 at 19:28

2 Answers2

4

str is not constructed. if you must use str you must either provide a constructor for it or construct it via placement new. A full example below

#include <iostream>
#include <vector>

using namespace std;

union Data
{
    int i;
    double x;
    std::string str;
    Data() {}
    Data(std::string st) : str(st) {}
    ~Data() {}
};

int main()
{
    Data var;
    var.x = 31293.932;
    new (&var.str) std::string("Hello World!");


    std::cout << var.x << "\n";
    std::cout << var.str << "\n";
    std::cout << var.i << "\n";

//destroy it
    var.str.std::string::~string();
}

EDIT:

Just to expand my answer a bit...

MSDN seems to have a n00bie friendly explanation about unions than cppreference. So, check: Unions - MSDN and Unions - cppreference

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • What does "new (&var.str) std::string("Hello World!");" really does? Does it allocate memory with size "Hello World!" or it just calls the constructor for Data? – meguli Feb 11 '16 at 19:56
  • Worth adding that since `i`, `x`, and `str` share the same space in memory, assigning to `i` or `x` after setting `str` will corrupt `str` and possibly render it undestroyable. – user4581301 Feb 11 '16 at 19:57
  • @meguli That's a Placement New. Read more here: [What uses are there for “placement new”?](http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new) – user4581301 Feb 11 '16 at 19:58
0

You should be using char to access the bytes in the union. std::string is not a POD type and can't be used in this way.

Try this instead:

union Data { 
    int i;
    double x;
    char bytes[sizeof(double)];
    ~Data(){}
};

union Data var = {.x = 31293.932};

std::cout << var.x << "\n";
std::cout.write(var.bytes, sizeof(var.bytes));
std::cout << "\n" << var.i << "\n";

The full definition of what a POD type is extensive. In very simple terms it is a basic data type without a explicitly-defined copy constructor, destructor, or virtual methods and does not itself contain any such types if it is an aggregate type (like struct, class, and unions).

Kurt Stutsman
  • 3,994
  • 17
  • 23