+ 2
Is it okay to use a C++ union like this?
I’ve provided the following code snippet. I would use this to capture the state of an object. For instance, it could be useful in an undo/redo algorithm. Is this okay to do? Are there better alternatives? https://code.sololearn.com/c5fCcr65K3sq/?ref=app
3 odpowiedzi
+ 1
> Is this okay to do?
No.
This statement in particular:
cout << "Buffer Data:\t" << buf.data << "\n";
is Undefined Behavior ( https://en.cppreference.com/w/cpp/language/ub )
> It's undefined behavior to read from the member of the union that wasn't most recently written.
- From https://en.cppreference.com/w/cpp/language/union
> Are there better alternatives?
To what? a union? Yes. Use `std::variant` ( https://en.cppreference.com/w/cpp/utility/variant ), think of it as the C++ version of a union.
But, I'm not sure why is a union needed in the provided example?
Why can't the code simply be:
template <typename T>
struct Buffer {
T value;
std::string data; // or std::array, or std::vector, or whatever
};
As for implementing an undo/redo system, the Command Pattern ( https://en.wikipedia.org/wiki/Command_pattern ) solves that problem.
A practical example can be found here: https://codereview.stackexchange.com/a/203678
0
Isho Thank you for your answer, I can see why that is undefined behavior. The reason I made it a char array, instead of a string or anything else, is to get the actual bytes of the T value. It’s not a normal use of a union, but I was just curious.
0
Note that 'std::string' doesn't *have to be* a "string" (a human readable array of characters).
> The class is dependent neither on the character type nor on the nature of operations on that type.
- https://en.cppreference.com/w/cpp/string/basic_string
You can use 'std::string' however you like, as long as the elements stored within are 'char's (std::string is an instantiation of std::basic_string<char>).
An example of how std::string is used to store raw bytes instead of human-readable strings is Google's Protobuf library ( https://github.com/protocolbuffers/protobuf ). They use std::string as a "convenient container" for the serialized message objects, nothing more.
Another way to store raw bytes is a 'std::vector<uint8_t>' (assuming a byte is an 8-bit value on the target platform).