C ++ STD :: вариант против STD :: любой - PullRequest
3 голосов
/ 25 мая 2019

C ++ 17 представляет std::variant и std::any, оба способны хранить различные типы значений в объекте. Для меня они чем-то похожи (не так ли?).

Также std::variant ограничивает типы записей, кроме этого. Почему мы должны предпочесть std::variant над std::any, который проще в использовании?

Ответы [ 3 ]

12 голосов
/ 25 мая 2019

Чем больше вещей вы проверяете во время компиляции, тем меньше у вас ошибок времени выполнения.

variant гарантирует, что он содержит один из списка типов (плюс бесполезный за исключением). Это дает вам возможность гарантировать, что работающий на нем код учитывает каждый случай в варианте с std::visit; даже каждый случай для пары из variant с (или более).

any нет. С any лучшее, что вы можете сделать, это «если тип не совсем то, что я запрашиваю, некоторый код не будет работать».

variant существует в автоматическом хранилище. any может использовать бесплатный магазин; это означает, что any имеет производительность, а noexcept(false) - проблемы, которые variant не имеет.

Проверка, для какого из N типов он есть, составляет O (N), для any - для variant это O (1).

any это наряд void*. variant это наряд union.

any не может хранить типы, не предназначенные для копирования или перемещения. variant банка.

Тип variant - документация для читателя вашего кода.

Передача variant<Msg1, Msg2, Msg3> через API делает операцию очевидной; пропуск any означает, что понимание API требует надежной документации или чтения источника реализации.

Любой, кто был разочарован статически не типизированными языками, поймет опасность any.

Теперь это не значит, что any - это плохо; это просто не решает те же проблемы, что и variant. Как копируемый объект для стирания типа, он может быть великолепным. Динамическая типизация во время выполнения имеет свое место; но это место не «везде», а «где вы не можете избежать его».

4 голосов
/ 25 мая 2019

Разница в том, что объекты хранятся в памяти, выделенной std::variant:

cppreference.com - стандартная версия :: вариант

Как и в случае союзов, если вариант содержит значение некоторого типа объекта T, представление объекта T размещается непосредственно в представлении объекта самого варианта. Варианту запрещается выделять дополнительную (динамическую) память .

и для std::any это невозможно.

На этом этапе std::variant требуется только одно выделение памяти для самого std::variant, и он может оставаться в стеке.

2 голосов
/ 25 мая 2019

Кроме того, что никогда не используется дополнительная память кучи, variant имеет еще одно преимущество:

Вы можете std::visit a variant, но не any.

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