2014-09-27 14 views
6

Mam pytanie dotyczące inteligentnych wskaźników w języku C++ 11. Zacząłem mieć spojrzenie na C++ 11 (zwykle program w języku C#) i przeczytać coś na temat inteligentnych wskaźników. Teraz mam pytanie, czy inteligentne wskaźniki całkowicie zastępują "stary" styl wskaźników, czy zawsze powinienem z nich korzystać?C++ 11 Inteligentne użycie wskaźnika

Wydaje się, że unique_ptr rozwiązuje wszystkie problemy związane z zarządzaniem pamięcią w C++, czy też się mylę?

Na przykład:

std::unique_ptr<GameManager> game (new GameManager()); 

game->Start(); 

Wydaje się być dużo bardziej inteligentne niż:

auto *game2 = new GameManager(); 

game2->Start(); 

delete game2; 

Dziękuję, jestem trochę zdezorientowany!

+6

Nie należy ich używać, gdy nie ma wątpliwości co do własności. Na przykład, jeśli coś jest właścicielem menedżera gier i coś innego chce z niego korzystać (na przykład polimorficznie) i nie ma nic do powiedzenia na temat jego własności lub okresu istnienia, można rozważyć przekazanie do niego surowego wskaźnika. – juanchopanza

+0

Dziękuję, teraz jest bardziej przejrzyste – BendEg

+5

"rozwiązać wszystkie problemy" - nie. Jednak rozwiązuje to wiele. –

Odpowiedz

6

Aby odpowiedzieć na pytanie: tak, rozwiązują one problemy z zarządzaniem pamięcią.

Uważa się, że dobrym stylem jest ich użycie w jak największym stopniu.

Eliminują wiele możliwych błędów programistycznych i zmniejszają trudność tworzenia poprawnego kodu za pomocą wskaźników.

pójść jeszcze dalej, to jest uważane za dobre, aby zmienić

std::unique_ptr<GameManager> game (new GameManager()); 

Do:

std::unique_ptr<GameManager> game (std::make_unique<GameManager>()); 
+1

Dziękuję za szybką odpowiedź, ale co to za odpowiedź na make_unique: http://stackoverflow.com/a/9657991/? – BendEg

+0

@ BendEg Jest w języku C++ 14 i jest powszechnie dostępny. –

+0

Ok, przeczytam coś o C++ 14, myślałem, że to jeszcze nie standard. (Używam mvC++) – BendEg

3

Oprócz jednolitej własności unique_ptr, istnieją także sytuacje, gdzie jest udostępniony, lub trudne do zdefiniowania własności. W takich przypadkach shared_ptr zapewnia zliczanie odwołań, a ostatni właściciel usunie odnośnik.

W przypadkach, w których shared_ptr może być zaangażowany w złożoną pętlę odniesienia, standard zapewnia również weak_ptr.

Wszystkie te elementy zastępują starszy auto_ptr.

9

Dla pokazanego użycia, podczas gdy unique_ptr jest lepszy niż wskaźnik surowy, ponieważ wskazuje na własność przydzielonych zasobów, prawdopodobnie nie należy używać żadnego wskaźnika w ogóle. Zamiast po prostu zadeklarować lokalny:

GameManager game; 
game.Start(); 

To może nie wystarczyć, jeśli własność może być podane do czegoś innego, podczas gdy prawo własności unique_ptr można łatwo przenosić.

+1

Podnoszę tę odpowiedź, ponieważ wskazuje ona - jak już wspomniano powyżej - że można bardzo dobrze żyć w C++ bez żadnych wskazówek, umieszczając obiekty na stosie. –

+0

To naprawdę powinna być zaakceptowana odpowiedź.Obecna akceptowana odpowiedź sprawia, że ​​brzmi to tak, jakby przydzielanie sterty lokalnie określanych instancji było lepsze niż przydzielanie stosów, co rzadko jest prawdą. –

3

Nie, nie zamień całkowicie wszystkich surowych wskazówek.

Używanie inteligentnych wskaźników (unique_ptr, shared_ptr) jest przydatne tylko dla wskaźników, które są właścicielami i zarządzają pamięcią wskaźnika. Jeśli jednak funkcja przyjmuje wskaźnik jako parametr, nie chcesz przenosić własności. Ta funkcja musi tylko uzyskać dostęp do wskaźnika.

void ShowCredits(GameManager* game) // Just use game, don't take ownership. 
{          // A raw pointer here is good. 
    // ... 
} 

void main() 
{ 
    auto game = make_unique<GameManager>(); // game owns the GameManager. 
    game->Start(); 
    ShowCredits(game.get()); 
} 

PS: Jeśli ShowCredits zależy od tego, czy gra jest zawsze ważna (tj.nie może opcjonalnie mieć wartości nullptr), w rzeczywistości może być lepiej, gdy parametr jest typu GameManager &.

+6

Zamiast przechodzić przez wskaźnik, należy przechodzić przez odniesienie do 'ShowCredits (GameManager & game);' –

+0

'main' powinien zwrócić' int'. – GingerPlusPlus