2012-03-31 9 views
16

Nie mogę stwierdzić ze standardu C++ 11, czy nullptr_t ma domyślny konstruktor. Innymi słowy, jest następujące ważne ?:Czy nullptr_t jest domyślnym typem możliwym do skonstruowania?

nullptr_t n; 

GCC i VC++ pozwalają powyższy kod, ale dzyń nie. Nie mogę znaleźć niczego w standardzie, określając, że nie ma on domyślnego konstruktora, a to, co mogę znaleźć, sugeruje, że powinno. Ma to dla mnie znaczenie, ponieważ piszę podstawową awaryjną implementację nullptr dla starszej obsługi kompilatora i muszę wiedzieć, czy muszę nadać mu domyślny konstruktor.

+0

Myślałem, że masz obsłużyć 'nullptr_t' jako zwykły typ wskaźnika, tj. Nie jako klasę. Zakładam, że 'nullptr_t n;' tworzy zmienną _uninitialised_; powinieneś jawnie napisać 'nullptr_t n = nullptr;'. Ale nie mam tu kompilatora C++ 11, więc nie mogę sprawdzić. I nie mogę znaleźć miejsca, w którym to przeczytałem w formalnych specyfikacjach ... –

+0

FWIW, clang akceptuje "nullptr_t n;" tutaj. –

Odpowiedz

17

co mówi Standard

Standardowe mówi (18,2)

nullptr_t jest zdefiniowany w następujący sposób:

namespace std { 
    typedef decltype(nullptr) nullptr_t; 
} 

typu, którego nullptr_t jest synonimem ma cechy opisane w 3.9.1 i 4.10.

Gdzie 3.9.1 mówi zasadniczo powinno być tej samej wielkości co void* i 4,10 określa zasady konwersji dla nullptr.

Edit: 3.9.9 ponadto wyraźnie stwierdza, że ​​nullptr_t jest skalarne typu, co oznacza oczekiwane zasady inicjowania dla wbudowanych typów od 8,5 zastosowanie:

  • Default-inicjalizacji (nullptr_t n;), który pozostawia nieokreśloną wartość n. Jak słusznie zauważył Johannes Schaub, kompilacja ta dobrze komponuje się z najnowszą wersją Clanga.
  • Wartość inicjalizacji (nullptr_t n = nullptr_t();), który inicjuje n 0.

to zachowanie jest identyczna np int, więc nullptr_t jest zdecydowanie domyślny-konstruktywny. Interesujące pytanie brzmi: co to oznacza, że ​​dla nullptr_t ma niezdefiniowaną wartość? Pod koniec dnia jest tylko jedna znacząca możliwa wartość dla nullptr_t, która jest nullptr. Ponadto sam typ jest definiowany tylko przez semantykę literału. Czy te semantyki nadal mają zastosowanie do unitialized value?

Dlaczego kwestia ta nie ma znaczenia w praktyce

Nie chcesz zadeklarować nową zmienną typu nullptr_t. Jedyny znaczący semantyczny tego typu jest już wyrażony poprzez literał, więc zawsze, gdy użyjesz niestandardowej zmiennej typu nullptr_t, równie dobrze możesz użyć nullptr.

Co ma znaczenie w praktyce

Jedyny wyjątek to wynika z faktu, że można wziąć non typu parametrów szablonu typu nullptr_t. W tym przypadku warto wiedzieć, które wartości można przekonwertować na nullptr_t, co opisano w punkcie 4.10:

null stały wskaźnik stanowi integralną wyrażenie stałe (5,19) prvalue typu liczby całkowitej, która ocenia zero lub prvalue typu std::nullptr_t. [...] Stała wskaźnika zerowego typu całkowego może zostać przekonwertowana na wartość typu std::nullptr_t.

które w zasadzie nie tylko to, co można się spodziewać: Można napisać

nullptr_t n = 0; // correct: 0 is special 

ale nie

nullptr_t n = 42; // WRONG can't convert int to nullptr_t 

Zarówno gcc 4.6 i Clang SVN uzyskać to prawo.

+1

Popełniasz błąd uogólniając coś, co jest prawdziwe w odniesieniu do klas do nie-klas. Non-classes nie mają żadnych funkcji członkowskich. –

+1

Typy nie należące do klasy mogą być domyślnie konstruowane bez funkcji składowej. Nie chodzi o posiadanie domyślnego konstruktora w sensie posiadania funkcji składowej, ale w sensie spełniania pojęcia typu domyślnego-konstruktywnego. – ComicSansMS

+0

Ze standardu: "Typ, dla którego nullptr_t jest synonimem, ma cechy opisane w 3.9.1 i 4.10." Odwiedź sekcję 3.9.1 (Typy podstawowe) i dowiedz się, że możesz zadeklarować zmienne typu int-typed, float-piter, a nawet nullptr_t-typed. –

1

Podczas nullptr to nowy dodatek do samego języka, std::nullptr_t tylko aliasem typu bezimiennego, alias zadeklarowane w cstddef tak:

typedef decltype(nullptr) nullptr_t; 

Podczas nullptr_t, będąc typedef a nie język słowo kluczowe, nie jest wymienione jako typ podstawowy, określono go jako typ podstawowy (a nie na przykład jako typ wskaźnika lub typ klasy). Dlatego nie ma domyślnego konstruktora, ale nadal możesz zadeklarować zmienną taką, jaką już zrobiłeś. Twoja zmienna nie została zainicjalizowana i zastanawiam się, jakie może być jej użycie i jaki komunikat o błędzie został wyświetlony od clang.

Zobacz także here.

+0

Myślę, że specyfikacja dotycząca wartości nullptr_t w sekcji "Typy podstawowe" sugeruje, że nullptr_t jest typem podstawowym. Nie ma wyraźnej listy typów, które są typami podstawowymi, co oznacza, że ​​należy je gromadzić poprzez powtarzanie wszystkich typów wymienionych w "Typach podstawowych". I ma wiele sensu, że i tak jest to typ podstawowy. –

+4

Pamiętaj, że nie możesz powiedzieć "Typ nullptr_t to biblioteka typedef". Typedef * nie * wprowadza nowego typu. Po prostu tworzy alias do istniejącego typu. Typ, który "nullptr_t" tworzy aliasy * jest * wprowadzony przez język. –

+0

@ JohannesSchaub-litb - OK, zredagowałem pytanie, aby wyjaśnić tę kwestię. Chodzi o to, że typ 'nullptr' nie ma nazwy ani aliasu w programie C++, dopóki nie zostanie przypisany alias (najlepiej zrobiony przy użyciu pliku nagłówkowego biblioteki standardowej). –

Powiązane problemy