2016-07-23 24 views
14

Jak pokazano here, std::unique_ptr ma dwa constexpr konstruktorów dla zerowych wskaźników:std :: unique_ptr constexpr konstruktorzy

constexpr unique_ptr(); 
constexpr unique_ptr(nullptr_t); 

Mam dwa pytania dotyczące tych dwóch konstruktorów:

  1. Dlaczego potrzebne są dwa ? Nie możemy po prostu zadeklarować jeden jako:

    constexpr unique_ptr(nullptr_t = nullptr); 
    
  2. Czy constexpr naprawdę przydatne? Próbowałem to zrobić w moim kodu, ale nie skompilować (g ++ 6.1.0, -std=c++14):

    constexpr std::unique_ptr<int> p; 
    // error: the type 'const std::unique_ptr<int>' of constexpr variable 'p' 
    // is not literal because 'std::unique_ptr<int>' has a non-trivial destructor 
    
+3

Który łączy z powrotem do tego samego pytania – Dutow

+0

@Dutow Hahahaha –

+0

Błąd kopiowania/wklejania LOL. Ale odpowiedź oldrinba łączy się z tą, którą miałem zamiar połączyć. –

Odpowiedz

14

Dla (1), uważają, że gwarantuje ona, że ​​zarówno no-Arg i konstruktor unique_ptr() Konstruktor null-pointer unique_ptr(nullptr_t) ma takie same gwarancje na czas kompilacji, tj. oba są constexpr. Widzimy różnicę w §20.8.1.2:

constexpr unique_ptr() noexcept; 
explicit unique_ptr(pointer p) noexcept; 
... 
constexpr unique_ptr(nullptr_t) noexcept 
: unique_ptr() { } 

Dlaczego dwa nie zostały połączone w jeden konstruktora z wartością domyślną jest prawdopodobnie historyczny awaryjny.

W odniesieniu do (2), dlatego powinniśmy dbać o constexpr pomimo nietrywialne destruktora rozważyć the answer given here:

constexpr konstruktorzy mogą być wykorzystywane do ciągłego inicjalizacji, która, jako forma statyczna inicjalizacja jest gwarantowana przed rozpoczęciem dynamicznej inicjalizacji.

Na przykład, biorąc pod uwagę globalną std::mutex:

std::mutex mutex; 

W zgodnym realizacji (czytaj: nie MSVC), konstruktorzy z innych przedmiotów można bezpiecznie zablokować i odblokować mutex, ponieważ posiadał konstruktor std::mutex „s jest constexpr.

9

odniesieniu do Q1, konstruktor nullptr_t dodano później N2435, a po pierwotnym wniosku (N1586).

Dodanie prostego przeciążenia, które można określić w jednym wierszu, jest znacznie czystsze, niż próba bycia sprytnym, zwłaszcza że funkcja [member.functions] pozwala już implementacji na użycie "sprytnej" wersji, jeśli chce.

+1

Zatem obecni dwaj lekarze określeni w normie powinni być funkcjonalnie równoważni temu z mojego pytania, zgadza się? –

Powiązane problemy