Kiedy używać wskaźników, a kiedy nie?

Jestem przyzwyczajony do programowania w Javie, gdzie nigdy nie trzeba myśleć o wskaźnikach podczas programowania. Jednak w tej chwili piszę program w C++. Kiedy należy używać wskaźników podczas tworzenia klas, które mają członków innych klas, a kiedy nie? Na przykład, kiedy chciałbym to zrobić:

class Foo {
    Bar b;
}

W przeciwieństwie do tego:

class Foo {
    Bar* b;
}
Author: Pukku, 2008-12-29

5 answers

Zacznij od unikania wskaźników.

Użyj ich, gdy:

  • chcesz użyć idiomu Pimpl , lub abstrakcyjna fabryka .
  • instancja Bar jest faktycznie zarządzana przez inną część twojego programu, podczas gdy klasa Foo musi tylko mieć do niej dostęp.
  • chcesz odłożyć budowę obiektu Bar (tzn. chcesz go utworzyć Po konstruowaniu Foo).
  • w logice biznesowej obiekt Bar może w ogóle nie istnieć; można użyć null również w Javie. Jednak sprawdź boost:: opcjonalne.
  • Bar jest w rzeczywistości klasą bazową, a instancja musi być polimorficzna.
  • zdarza Ci się używać zestawu narzędzi, który woli prezentować widżety GUI jako wskaźniki. Przykłady mogą obejmować (ale z pewnością nie są ograniczone do) wxWidgets i GLUI.

W każdym z tych przypadków (*), zacznij od użycia inteligentnego wskaźnika, takiego jak boost:: shared_ptr. W przeciwnym razie prawdopodobnie zapomnisz dealokacji pamięci, prędzej czy później. Gdy już wiesz, co robisz, zastanów się indywidualnie, jaki typ wskaźnika jest najlepszy.

( * ) każdy przypadek-z wyjątkiem, prawdopodobnie, punkt dotyczący widżetów GUI; w tym przypadku, twój zestaw narzędzi prawdopodobnie będzie zarządzać zasobami dla Ciebie, jak również

 39
Author: Pukku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-29 07:59:16
class Foo {
    Bar b;
}

B jest zawarte W Foo. Jeśli obiekt Foo zakończy żywotność, b automatycznie zakończy również żywotność. To właśnie skład modeli. b powyżej oznacza sam obiekt, a nie tylko wskaźnik do niego, jak w Javie. W związku z tym, jeśli b wyjdzie poza zasięg, obiekt zakończy żywotność.

class Foo {
    Bar * b;
}

Tutaj obiekt B wskazuje na używany przezlub odnoszony przez obiekt Foo. Jeśli obiekt Foo zakończy żywotność, obiekt b wskazuje na to, że może nadal żyć, w zależności od okoliczności. Można to wykorzystać do modelowania agregacji i ogólnej relacji. Obiekt może być współdzielony na przykład z innymi obiektami Foo.

Wskaźniki są mniej więcej tym, czym są odniesienia w Javie. Mogą też do niczego nie wskazywać. Jeśli wskaźnik nie wskazuje na nic, jest to wskaźnik null.

Podobnie jak wskaźniki są odniesieniami. Odniesienia w C++ muszą być zainicjalizowane i mogą wskazywać tylko na jeden (ważny) obiekt, dla którego odniesienie zostało zainicjowane. Odniesienie do niego nie może zawierać wartości co może oznaczać " nic " jak null w Javie.

 19
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-01 10:51:53

W pierwszym przykładzie pamięć dla obiektu Bar zostanie przydzielona automatycznie podczas konstruowania obiektu Foo. W drugim przypadku musisz samodzielnie przydzielić pamięć. Więc musisz zadzwonić:

Foo *foo = new Foo();
foo->b = new Bar();

Może to być pożądane, jeśli obiekt Bar jest duży i nie chcesz wiązać go z obiektem Foo. Jest to również pożądane, gdy budowa obiektu Bar jest niezależna od tworzenia obiektu Foo. W tym przypadku obiekt b jest "wtryskiwany" do foo:

Foo *foo = new Foo();
foo->b = b_ptr;

Gdzie b_ptr jest skonstruowany gdzie indziej i wskaźnik jest przekazywany do foo.

Dla mniejszych obiektów jest to niebezpieczne, ponieważ możesz zapomnieć o przydzieleniu pamięci.

 3
Author: kgiannakakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-29 07:50:31

Oba są w porządku w różnych warunkach. Na przykład, jeśli wiesz, jak skonstruować b, gdy obiekt klasy Foo jest skonstruowany, pierwsza jest OK. Ale jeśli nie, jedynym wyjściem jest użycie drugiego.

 1
Author: PolyThinker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-29 07:10:29

Musisz trochę zaprogramować montaż i dobrze zrozumieć układ pamięci. C jest po prostu złożeniem wieloplatformowym, w przeciwieństwie do Javy lub innych języków. Aby go właściwie używać, należy zrozumieć szczegóły niskiego poziomu.

Wszystkie komentarze są ważne, ale dla osób takich jak ty, którzy przeskakują z języków wysokiego poziomu do języka C, posiadanie tego rodzaju doświadczenia byłoby więcej niż korzystne. Przy odpowiednim zrozumieniu, nie zadawałbyś już takich pytań.

 1
Author: valenok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-29 20:19:52