C ++ союз присваивания, есть ли хороший способ сделать это? - PullRequest
2 голосов
/ 18 марта 2010

Я работаю над проектом с библиотекой, и я должен работать с профсоюзами. В частности, я работаю с SDL и объединением SDL_Event . Мне нужно сделать копии SDL_Events, и я не смог найти хорошей информации о перегрузке операторов присваивания с объединениями.

При условии, что я могу перегрузить оператор присваивания, должен ли я вручную просеять через членов объединения и скопировать соответствующие члены, или я могу просто прийти к некоторым членам (это кажется мне опасным), или, возможно, просто использовать memcpy () (это кажется просто и быстро, но немного опасно)?

Если я не могу перегрузить операторов, какими будут мои лучшие варианты? Я думаю, что я мог бы сделать новые копии и обойти кучу указателей, но в этой ситуации я бы предпочел не делать этого.

Любые идеи приветствуются!

EDIT: По запросу сообщений об ошибках, и, кстати, я думаю, что я узнал что-то ...

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: Это было так глупо ... Я думал, что элемент Deqeues pop () вернул удаленный элемент. Я думал, что код настолько прост, что не может быть моим кодом, но это оказалось неправильно.

мой код выглядел так:

 for(SDL_Event CurrentEvent; !DequeueOfSDLEvents.empty(); CurrentEvent = DequeueOfSDLEvents.pop() )
 {
   //Do stuff
 }

Так что, если ничего другого, я научусь более внимательно изучать функции-члены контейнеров, которые я недавно не использовал. Спасибо за объяснение назначения по умолчанию, иначе это заняло бы больше времени.

Ответы [ 6 ]

5 голосов
/ 18 марта 2010

В объединении все элементы занимают одну и ту же память, как будто они сидят друг на друге. Если вы пишете в другой элемент объединения, он перезаписывает другие.

Таким образом, копирование элемента за элементом является пустой тратой времени. Вы можете скопировать только самый большой элемент, но тогда вам нужно будет знать, какой из них (не все элементы объединения должны быть одинакового размера). Лучше всего просто запоминать объединение.

Но это даже проще, вы должны просто выполнить присваивание, и компилятор, понимая, что вы копируете структуру или объединение, будет неявно выполнять для вас "memcpy".

3 голосов
/ 18 марта 2010

Поскольку объединениям (по определению) разрешено содержать только POD, вы можете безопасно использовать memcpy для их копирования.

1 голос
/ 18 марта 2010

Я могу ошибаться, но разве профсоюзы не поддерживают назначение из коробки?

#include <cassert>

union X
{
    int a;
    double b;
};

int main()
{
    X x;
    x.a = 10;
    X y;
    y = x;
    assert(y.a == x.a);
}

Похоже, вы также можете перегрузить оператор = для него как обычно, но чем именно вы хотите отличаться от обычного назначения по умолчанию?

0 голосов
/ 18 марта 2010

Вам не нужно делать ничего особенного. По моему мнению, перегрузка или добавление операторов только добавит сложности. SDL_event - это простой неподписанный символ.

SDL_Events a;
SDL_Events b;

a = b;  // this will copy the value
0 голосов
/ 18 марта 2010

Вообще говоря, вы можете просто использовать сгенерированный компилятором оператор присваивания. Единственное исключение, о котором я могу подумать, - это если у вас есть объединение, которое может содержать указатель, и вы хотите реализовать глубокую копию для этого указателя. Для того, чтобы справиться с этим, вам нужно сделать его объединенным, чтобы вы могли определить тип и соответствующим образом скопировать указатель. Однако, если у вас нет удаленного владения, сгенерированное компилятором назначение (и копия ctor) должно работать нормально.

0 голосов
/ 18 марта 2010

Похоже на типичный вариант использования boost :: option

[Изменить] Почему не подходит?

#define BOOST_VARIANT_LIMIT_TYPES 14
typedef boost::variant<Uint8, SDL_ActiveEvent, SDL_KeyboardEvent, ...,SDL_SysWMEvent> MyEvent;
...