2012-08-09 14 views
12

I realisierte die folgend in GCC 4.7 Fein kompiliert:Kann ich einem shared_ptr 0 zuweisen? Warum?

#include <memory> 

int main() { 
    std::shared_ptr<int> p; 
    p = 0; 
} 

Es gibt jedoch keinen Zuweisungsoperator aus int oder von int*, und es gibt keinen impliziten Konstruktor entweder intint* oder auch nicht. Es gibt einen Konstruktor von int*, aber dieser ist explizit. Ich überprüfte die Implementierung der Standardbibliothek und der Konstruktor ist in der Tat explizit, und keine fischigen Zuweisungsoperatoren sind in Sicht.

Ist das Programm wirklich wohlgeformt oder spielt GCC mit mir?

+4

'0' ist das spezielle Literal, es konvertiert zu' nullptr_t' – Abyx

+2

@LucDanton es ist, weil g ++ sehr schlau ist und '42 - 42 'in' 0' konvertiert. Das gleiche passiert (passiert?) In Clang, IIRC, es wurde bei GN2012 erwähnt – Abyx

+5

@Abyx Sie haben den Punkt verfehlt - '0' hat keine besondere Behandlung als Literal in der Sprache. –

Antwort

16

Der Grund, dies funktioniert, ist diese kurze Zitat aus dem Standard:

§4.10 [conv.ptr] p1

Ein Nullzeiger Konstante ist ein Integralkonstante Ausdruck (5.19) prvalue ganzzahliger Typ , die auf Null auswertet oder ein Prvalue des Typs std::nullptr_t. [...] Eine Null-Zeiger-Konstante vom Integraltyp kann in einen Pr-Wert vom Typ std::nullptr_t konvertiert werden. [...]

Und die Tatsache, dass std::shared_ptr einen impliziten Konstruktor von std::nullptr_t hat:

§20.7.2.2 [util.smartptr.shared] p1

constexpr shared_ptr(nullptr_t) : shared_ptr() { }

Dies ermöglicht auch für Seltsamkeiten wie folgt aus:

#include <memory> 

void f(std::shared_ptr<int>){} 

int main(){ 
    f(42 - 42); 
} 

Live example.

+7

In Bezug auf Kuriositäten wie 42 - 42, die Null-Zeiger-Konstanten sind, geht das wahrscheinlich weg, und [nur ein Literal 0 wird eine gültige Null-Zeiger-Konstante sein] (http://www.open-std.org/jtc1/sc22/wg21/ docs/cwg_active.html # 903), in einer zukünftigen Version von C++. – hvd

+0

@hvd: Interessant, danke dafür! – Xeo

0

können Sie nur einen freigegebenen Zeiger auf eine andere Instanz eines gemeinsamen Zeiger zuweisen. Das Zuweisen des Typs, den shared_pointer enthält, ist nicht möglich. AFAIK ist dies die einzige Überlast für den Betreiber:

shared_ptr& operator=(const shared_ptr& r);

Was machst du 0 zuweist (die in diesem Fall gleich NULL) auf den Zeiger, nicht der Wert des Typs. Ihr Typ wird an dieser Stelle im Code nicht einmal initialisiert.

+0

Das geht nicht wirklich auf die Frage ein: "Warum akzeptiert der Compiler das ohne Beanstandung?" – Flexo

Verwandte Themen