2016-07-23 24 views
14

Wie gezeigt here, std::unique_ptr hat zwei constexpr Konstrukteuren für Null-Zeiger:std :: unique_ptr constexpr Konstrukteuren

constexpr unique_ptr(); 
constexpr unique_ptr(nullptr_t); 

Ich habe zwei Fragen für diese beiden Konstrukteure:

  1. Warum brauchen wir zwei ? Können wir nicht erklären, nur ein Beispiel:

    constexpr unique_ptr(nullptr_t = nullptr); 
    
  2. Ist das constexpr wirklich nützlich? Ich habe versucht, dies in meinem Code zu tun, aber es hat nicht kompilieren (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

Das verweist auf die gleiche Frage – Dutow

+0

@Dutow Hahahaha –

+0

LOL Kopie/einfügen fehlgeschlagen. Aber die Antwort von oldrinb verweist auf die, die ich verlinken wollte. –

Antwort

14

Für (1), die Ansicht, dass es gewährleistet, dass sowohl der nicht-arg Konstruktor unique_ptr() und Nullzeiger Konstruktor unique_ptr(nullptr_t) haben die gleichen Kompilierzeit Garantien, dh beide sind constexpr. Wir können den Unterschied in §20.8.1.2 sehen:

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

Warum waren die beiden nicht mit einem Standardwert in einem einzigen Konstruktor kombiniert ist wahrscheinlich historische Kontingenz.

In Bezug auf (2), warum sollten wir uns constexpr trotz einer nicht-trivial destructor kümmern, betrachten the answer given here:

constexpr Konstrukteure können für konstante Initialisierung verwendet werden, die als eine Form von statischen Die Initialisierung wird garantiert, bevor eine dynamische Initialisierung stattfindet.

Zum Beispiel gegeben globalen std::mutex:

std::mutex mutex; 

In einer konformen Implementierung (sprich: nicht MSVC), Konstrukteure anderer Objekte können sicher sperren und entsperren mutex, becuase std::mutex ‚s Konstruktor constexpr ist.

9

In Bezug auf Q1, der nullptr_t Konstruktor wurde später in N2435, auch nach dem ursprünglichen Vorschlag (N1586) hinzugefügt.

Das Hinzufügen einer einfachen Überladung, die in einer Zeile angegeben werden kann, ist viel sauberer als der Versuch, clever zu sein, zumal [member.functions] der Implementierung bereits erlaubt, die "clevere" Version zu verwenden.

+1

Also die aktuellen zwei Ctors, die in der Norm angegeben werden, sollten funktional äquivalent zu dem in meiner Frage sein, richtig? –

Verwandte Themen