Union vs. static_cast (void *) - PullRequest
       51

Union vs. static_cast (void *)

2 голосов
/ 20 августа 2011

Я пишу код, и до сих пор я использовал такие структуры:

struct s{
  enum Types { zero = 0, one, two };
  unsigned int type;
  void* data;
} 

Мне нужна была общая структура для хранения данных из разных классов, и я хотел использовать ее в std :: vector,вот почему я не могу использовать шаблоны.Какой вариант лучше: союзы или указатели void?

Указатель void выделяет столько места, сколько мне нужно, но c ++ по какой-то причине является языком со строгой типизацией, и приведение везде, где мне нужно, использует эти данные не так, как код c ++должен быть разработан.Как я читал, указатели void не должны использоваться, если нет альтернативы.

Эта альтернатива может быть Союзы.Они поставляются с c ++ и используют одинаковое пространство памяти для каждого члена, очень похоже на указатели void.Однако они имеют цену - выделенное пространство является размером самого большого элемента в объединении, и в моем случае различия между размерами велики.

Это довольно стилистическая и проблема «правильного использования языка», поскольку оба способа достигают того, чтоМне нужно это сделать, но я не могу решить, может ли красиво стилизованный код c ++ платить за эту потерянную память (хотя память в наши дни не представляет большой проблемы).

Ответы [ 3 ]

5 голосов
/ 20 августа 2011

Рассмотрим boost::any или boost::variant, если вы хотите хранить объекты разнородных типов.

И прежде чем решить, какой использовать, взгляните на сравнение:

Надеюсь, это поможет вам принять правильное решение. Выберите один и любой контейнер из стандартной библиотеки для хранения объектов, std::vector<boost::any>, std::vector<boost::variant> или любой другой.

1 голос
/ 20 августа 2011

Если у ваших классов достаточно общего, чтобы их можно было поместить в один и тот же контейнер, предоставьте им базовый класс с виртуальным деструктором и, возможно, виртуальной функцией-членом для получения кода вашего типа, даже если в этот момент не только dynamic_cast будет более целесообразно, но было бы разумно выяснить, недостаточно ли у ваших классов общего, чтобы предоставить им более полный общий интерфейс.

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

1 голос
/ 20 августа 2011

boost::variant.

По сути, это типобезопасное объединение, и в этом случае кажется, что объединения являются безусловно наиболее подходящим ответом.Можно использовать void*, но это будет означать динамическое распределение, и вам придется поддерживать Types enum и таблицу для приведения.

Ограничения памяти могут сделать void* приемлемымвыбор, но это не «аккуратный» ответ, и я бы не стал его использовать до тех пор, пока boost::variant и просто union не покажутся неприемлемыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...