2010-04-28 7 views
12

Głupie pytanie, ale czy kiedykolwiek dzwonisz nowy, zawsze masz wskaźnik?"nowy" operator w C++, pointer pytanie

SomeClass *person = new SomeClass(); 

A czy to dlatego, że potrzebujesz wskaźnika wskazującego na tę nową przestrzeń pamięci, która została przydzielona dla osoby zmiennej SomeClass? Dzięki!

+1

Zobacz także http://stackoverflow.com/questions/2697892/. – sbi

Odpowiedz

15

Jeśli new zakończy się pomyślnie, zawsze zwraca wskaźnik (jeśli nie zakończy się pomyślnie, zostanie zgłoszony wyjątek i nic nie zostanie zwrócone).

Wskaźnik jest do obiektu, który został utworzony, lub w przypadku tablicy, wskaźnik do pierwszego elementu tablicy.

+1

Można zrobić 'MyClass * p = new (std :: nothrow) MyClass'. Tutaj, w przypadku niepowodzenia, zamiast zwracania zwracana jest wartość [wskaźnik zerowy] (http://www.cplusplus.com/reference/new/operator%20new/). –

0

Nowe wyrażenie zwraca wskaźnik, ale można go użyć z klasami "inteligentnego wskaźnika" (np. from Boost). Więc:

 
boost::shared_ptr<SomePerson> person(new SomePerson); 

I należy również podkreślić, że choć może być używany do używania nawiasów jeśli pochodzą ze środowiska Java, C++, nawiasy nie są przy użyciu domyślnego konstruktora potrzebne. Na przykład, zwykle pisze new T podczas domyślnego konstruowania, ale jeden pisze new T(param) lub new T(param1,...,paramN) podczas konstruowania obiektu przy użyciu konstruktora innego niż domyślny.

Tak, zgadza się; teoretycznie można pisać (new SomePerson) -> doSomething(), ale byłby to przeciek pamięci; C++ nie ma zbierania śmieci, więc konieczne jest zapisanie wyniku w nowym wyrażeniu (wskaźniku lub wskaźniku inteligentnym), aby można go było poprawnie zwolnić.

+3

Zauważ, że 'new T' i' new T() 'mają różne wyniki dla typów POD i typów klas bez konstruktorów deklarowanych przez użytkownika:' new T() 'będzie wartościować zainicjować obiekt, a' new T' nie. –

+0

@ James, tak, jestem tego świadomy; jednak SomePerson jest najprawdopodobniej klasą. –

+0

Niezależnie od tego czy puste pareny mają znaczenie w wyrażeniu "nowy", to jeden z małych koszmarów C++: http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-match-a- difference-with-new/620402 # 620402 –

3

Tak, zawsze wskaźnik. Nawet jeśli chcesz przeładować nowy, typem zwrotu musi być void *.
Masz rację co do celu

1

Tak. Jeśli pytasz, dlaczego nie zwraca referencji zamiast tego, ponieważ odniesienia są ładniejsze niż wskaźniki, odpowiedź jest dziedzictwem historycznym.

Gdy C++ było w fazie rozwoju, jeśli maszyna nie mogła uzyskać pamięci dla obiektu, zwracany był specjalny wskaźnik NULL. To jak to się robi w C:

SomeClass *person; 
person = (SomeClass*) malloc(sizeof(SomeClass)); 
if (person == NULL) fprintf(stderr, "no more people allowed!"); 

W standardowej C++, błędy są zwracane przez wyjątkiem Zamiast:

try { 
    SomeClass *person = new SomeClass; 
    // do something 
} catch (std::bad_alloc) { 
    std::cerr << "no more people!" << std::endl; 
} catch (...) { 
    // using exceptions allows for other errors 
    // from inside SomeClass::SomeClass too 
} 

Nadal można zrobić w staromodny sposób, choć z nothrow:

SomeClass *person = new(std::nothrow) SomeClass; 
if (person == NULL) std::cerr << "no more people allowed!" << std::endl; 

Skutek jest taki, jest to całkowicie uzasadnione i dobry styl:

SomeClass &person = * new SomeClass; // don't need no stinkin pointers! 
+4

** SomeClass & person = * new SomeClass; ** - Nie sądzę, że jest to dobry styl, ponieważ używasz go jako zmiennej automatycznej i nadal musisz pamiętać, aby go usunąć w końcu zakresu. Prosty sposób na wycieki memów, IMO. I wielka niespodzianka dla kogoś, kto utrzyma twój kod –

+1

Myślę, że większość uznałaby ostatni przykład złego stylu. Chociaż w pewnym momencie można uzyskać wskaźnik, staje się mniej jasne, że obiekt jest dynamicznie przydzielany i musi zostać usunięty. Musisz także martwić się o dzień, w którym ktoś zastąpi typ referencyjny klasą bazową w sytuacji wielokrotnego dziedziczenia - wtedy możesz nie być w stanie odzyskać przydzielonego wskaźnika! –

+0

@Alexander, @Nick: użycie 'new', jeśli obiekt nie znajduje się gdzieś poza zasięgiem lokalnym, jest ** złym projektem **, i żadna ilość stylu nie może tego zrekompensować. – Potatoswatter

2

new tworzy obiekt na stercie, a wszystko, co może zwrócić, to jego adres - wskaźnik.