问题
I am working on a project with a library and I must work with unions. Specifically I am working with SDL and the SDL_Event union. I need to make copies of the SDL_Events, and I could find no good information on overloading assignment operators with unions.
Provided that I can overload the assignment operator, should I manually sift through the union members and copy the pertinent members or can I simply come some members (this seems dangerous to me), or maybe just use memcpy() (this seems simple and fast, but slightly dangerous)?
If I can't overload operators what would my best options be from there? I guess I could make new copies and pass around a bunch of pointers, but in this situation I would prefer not to do that.
Any ideas welcome!
EDIT: as requested Errors messages, and incidentally I think I have learned something...
physworld.cpp:325: error: no match for ‘operator=’ in ‘CurrentEvent = ((physworld*)this)->physworld::SDL_UserInputEvents.std::queue<_Tp, _Sequence>::pop [with _Tp = SDL_Event, _Sequence = std::deque<SDL_Event, std::allocator<SDL_Event> >]()’ /usr/include/SDL/SDL_events.h:220: note: candidates are: SDL_Event& SDL_Event::operator=(const SDL_Event&)
EDIT2: This was so stupid... I thought that Deqeues pop() member returned the item removed. I thought the code was so simple that it couldn't directly be my code, but that turned out to be wrong.
my code looked like:
for(SDL_Event CurrentEvent; !DequeueOfSDLEvents.empty(); CurrentEvent = DequeueOfSDLEvents.pop() )
{
//Do stuff
}
So if nothing else I will learn to look more closely at member functions of containers I haven't used recently. Thanks for explaining assignment worked by default, otherwise It would have taken longer to find this.
回答1:
In a union, the elements all occupy the same memory, like they sit on top of each other. If you write to another element of a union, it overwrites the others.
As such, copying element by element is a waste of time. You could copy the largest element only, but then you would have to know which one that is (not every element of the union has to be the same size) Best thing to do is to just memcpy the union.
But its even simpler than that, you should be able to just do an assignment, and the compiler, realizing you are copying a struct or union, will do the "memcpy" for you implicitly.
回答2:
Since unions are (by definition) only allowed to contain PODs, then you can safely use memcpy
to copy them.
回答3:
I may be mistaken, but don't unions support assignment out of the box?
#include <cassert>
union X
{
int a;
double b;
};
int main()
{
X x;
x.a = 10;
X y;
y = x;
assert(y.a == x.a);
}
It also appears you can also overload operator= for it as usual, but what exactly would you want to be different than in normal default assignment?
回答4:
Generally speaking, you can just use the compiler-generated assignment operator. The only exception I can think of would be if you had a union that could contain a pointer, and you wanted to implement a deep copy for that pointer. To handle that well, you'd have to make it a discriminated union so you could determine the type and copy the pointer appropriately. As long as you don't have remote ownership, however, the compiler-generated assignment (and copy ctor) should work fine.
回答5:
You don't need to do anything special. In my opinion overloading or adding operators would only add complexity. The SDL_event is a simple unsigned char.
SDL_Events a;
SDL_Events b;
a = b; // this will copy the value
回答6:
Looks like a typical use case of boost::variant
[Edit] Why not appropriate?
#define BOOST_VARIANT_LIMIT_TYPES 14
typedef boost::variant<Uint8, SDL_ActiveEvent, SDL_KeyboardEvent, ...,SDL_SysWMEvent> MyEvent;
来源:https://stackoverflow.com/questions/2466486/c-union-assignment-is-there-a-good-way-to-do-this