2017-02-07 11 views
33

Proszę wyjaśnić, jaka jest różnica między union a std::variant i dlaczego std::variant zostało wprowadzone do standardu? W jakich sytuacjach powinniśmy używać std::variant na oldschool'owym union?Gdzie użyć std :: variant over union?

+2

Myślę, że "union" nie zezwala na obiekty inne niż POD. I nawet jeśli tak to robi (tzn. Program nie ulega natychmiastowemu zawieszeniu), nie zapewnia wywołania właściwego destruktora. – yeputons

+9

Wszędzie, gdzie chcesz wpisać bezpieczeństwo i pracujesz z nietrywialnymi typami. – user975989

+1

Mam sprzeczność i nieporozumienie na temat std :: variant podczas oglądania tego filmu przez Jason Turner: https://www.youtube.com/watch? V = 3wm5QzdddYc –

Odpowiedz

48

Ogólnie rzecz biorąc, należy wolisz variant chyba jeden z następujących podchodzi:

  1. Oszukujesz. Robisz typowanie lub inne rzeczy, które są UB, ale masz nadzieję, że twój kompilator nie złamie twojego kodu.

  2. Wykonujesz niektóre z pseudo-punkenów, które mogą być wykonywane przez C++ union: konwersję między typami zgodnymi z układem lub między typowymi sekwencjami początkowymi.

  3. Użytkownik wyraźnie potrzebuje nieznacznej możliwości kopiowania i/lub zgodności układu. variant<Ts> nie muszą mieć określonego układu ani łatwej kopiowalności. unions standardowych typów układów to układ standardowy, a trywialnie kopiowane typy union można kopiować trywialnie.

    Należy pamiętać, że istnieje a proposal to make variant trivially copyable if its component types are trivially copyable. Jest on proponowany jako raport dotyczący wady w stosunku do C++ 17, więc to zachowanie zostałoby skutecznie przeniesione do C++ 17.

  4. Potrzebujesz wsparcia niskiego poziomu do przełączania obiektów w miejscu. Używanie bufora pamięci dla takich rzeczy nie zapewnia trywialnych gwarancji kopiowania, które można uzyskać z union.

Podstawową różnicą między nimi jest, że variantwie który wpisz je przechowuje, a union spodziewa się śledzić, które z zewnątrz. Jeśli więc spróbujesz uzyskać dostęp do niewłaściwej pozycji w variant, otrzymasz wyjątek lub nullptr. Natomiast wykonanie z wartością union jest jedynie niezdefiniowanym zachowaniem.

union to narzędzie niższego poziomu, a zatem powinno być używane tylko wtedy, gdy bezwzględnie potrzebujesz niższego poziomu.

variant posiada również maszyny do prowadzenia wizytacji, co oznacza, że ​​można dostać się do uniknięcia konieczności pęczek if sprawozdania gdzie zapytać „czy jest typu X, to zrobić. Jeśli jest typu Y, zrobić, itp.”

+10

"tylko niezdefiniowane zachowanie" nie jest frazą, którą widzę bardzo często. :-) * Doskonała * odpowiedź, chociaż. "Motywacja" jest tu główną motywacją i wydaje się obejmować w dużej mierze 2 i 4. –

+2

@CodyGray: # 2 i # 4 są całkowicie zgodne z prawem. Naprawdę nie oszukują tak bardzo, jak rzeczy, które wyglądają, jakby oszukiwały. –

Powiązane problemy