2012-08-09 3 views
12

uświadomieniu sobie następujące kompiluje GCC 4.7:Czy mogę przypisać 0 do shared_ptr? Czemu?

#include <memory> 

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

Jednakże, nie ma zadanie operatora z int lub int* i nie ma bezpośredniej konstruktor albo int lub int* obu. Jest konstruktor od int*, ale ten jest wyraźny. Sprawdziłem implementację standardowej biblioteki, a konstruktor jest rzeczywiście wyraźny i nie widać żadnych rybackich operatorów przypisania.

Czy program jest rzeczywiście dobrze sformułowany, czy GCC jest ze mną w kontakcie?

+4

'0' jest specjalnym dosłownym, zamienia na' nullptr_t' – Abyx

+2

@LucDanton, ponieważ g ++ jest bardzo inteligentny i konwertuje '42-42' na' 0'. To samo dzieje się (zdarzało się?) W Clang, IIRC, wspomniano o nim na GN2012 – Abyx

+5

@Abyx Tęskniłeś za punktem - "0" nie ma specjalnego traktowania jako literału w tym języku. –

Odpowiedz

16

Powodem tego działa jest to krótki cytat z normą:

§4.10 [conv.ptr] p1

null stały wskaźnik jest integralną stałym wyrażeniem (5.19) prvalue rodzaju integer który ocenia na zero lub prvalue typu std::nullptr_t. [...] Stała wskaźnika pustego typu całkowego może zostać przekonwertowana na wartość typu std::nullptr_t. [...]

A fakt, że std::shared_ptr ma niejawny konstruktor std::nullptr_t:

§20.7.2.2 [util.smartptr.shared] p1

constexpr shared_ptr(nullptr_t) : shared_ptr() { }

Pozwala to również na osobliwości tak:

#include <memory> 

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

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

Live example.

+7

Jeśli chodzi o dziwactwa, takie jak 42 - 42 będące stałymi wskaźnikami zerowymi, to najprawdopodobniej odejdzie, a [tylko literalna 0 będzie poprawną stałą wskaźnika zerowego] (http://www.open-std.org/jtc1/sc22/wg21/ docs/cwg_active.html # 903), w przyszłej wersji C++. – hvd

+0

@hvd: Interesujące, dzięki za to! – Xeo

0

można przypisać tylko wspólny wskaźnik do innej instancji wspólnego wskaźnika. Przypisanie typu hold_poznany hold nie jest możliwe. AFAIK jest to tylko przeciążenie dla operatora:

shared_ptr& operator=(const shared_ptr& r);

Co robisz jest przypisywanie 0 (który w tym przypadku jest równa null) do wskaźnika, a nie wartość typu. Typ wpisu nie jest jeszcze inicjowany w tym momencie kodu.

+0

To naprawdę nie odpowiada na pytanie: "dlaczego kompilator akceptuje to bez skargi" – Flexo