Gołe wskaźniki w dużych projekach

0

Witam,
Tak się ostatnio zastanawiam. Czy przy duzych projektach naprawdę rozbudowanych, opłaca się używać gołych wskaźników?
Generalnie problem ze wskaźnikami (nie inteligentnymi jak np atuo_ptr) jest taki, że w przypadku

 
MojaKlasa* klasa = new MojaKlasa();
//...coś się dzieje
delete klasa;

gdy coś się stanie w miejscu komentarza mamy wyciek pamięci.

Przy dużym projekcie taka sytuacja i taki wyciek to wydaje mi się tylko kwestia czasu.

0

Ja bym raczej unikał używania gołych wskaźników. boost Twoim przyjacielem :D

1

Czy przy duzych projektach naprawdę rozbudowanych, opłaca się używać gołych wskaźników?
Co to znaczy, „czy się opłaca”. Czasami trzeba.
Oczywiście można kombinować ze wskaźnikami „inteligentnymi” ale nie wszyscy je znają, a ci co znają niekoniecznie prawidłowo znają — poza tym to ubrzydza kod.
Już nie mówiąc o r-value referencjach, bo to już prawdziwa „puszka z pandorą”.

boost Twoim przyjacielem
Nie w każdym projekcie BOOST jest do przyjęcia, poza tym patrz argumenty wyżej.

A mówimy o „duzych projektach naprawdę rozbudowanych”. Jeśli nad kodem siedzi kilkadziesiąt osób, powinien być raczej prosty i zrozumiały a nie gonić za nowościami...

(w jednoosobowym projekcie, w którym wszystko znamy i nad wszystkim panujemy, jak najbardziej)

0

BOOST nie nazwałbym tu nowością, zresztą nawet bez tego w bibliotece standardowej są inteligentne wskaźniki i raczej zbyt skomplikowane one nie są. No ale jednak jak część zespołu ich nie zna no to rzeczywiście pozamiatane, albo się nauczą, albo trzeba z nich zrezygnować.

Oczywiście nie w każdym momencie i sytuacji jest sens używania inteligentnych wskaźników, ale jak jakiś obiekt lata pomiędzy różnymi instancjami różnych klas, do tego jeszcze mogą w to być zamieszane wątki to w takim wypadku się bardzo ładnie sprawdzają.

Co do czytelności kodu, to rzeczywiście trochę zaciemniają, ale z drugiej strony są nieocenione w sytuacji w której moment zwolnienia pamięci nie jest taki oczywisty. No i ograniczają problemy ze zwalnianiem pamięci np. w przypadku rzucania wyjątku - nie trzeba pamiętać, że trzeba to i to jeszcze zwolnić.

0

Azarien,
a kiedy goły wskaźnik trzeba użyć tak, że inteligentnego wręcz nie można?
Co z takim przypadkiem jak podałem, że stanie się coś czego nie przewidzimy, i mamy wyciek pamięci?

I pytanie brzmiące trochę lamersko:
czy sądzisz, ze zespoły piszące w C++ np duże gry, pisza je używając tylko/głównie gołych wskaźników?

1

Gołe wskaźniki nadal są przydatne, do przekazywania obiektów bez przekazywania własności. Z kolei używanie delete robi się deprecated. Dopiero teraz w standardzie są działające inteligentne wskaźniki i w dużej większości przypadków nie ma potrzeby jawnie zwalniać wskaźników. Składnia aż taka zła nie jest, a przechowuje trochę dodatkowych informacji o naturze zmiennej znacznie ułatwiając zarządzanie pamięcią w skomplikowanych przypadkach. Jak przerzucasz wskaźnik jak popadnie to i tak potrzebny ci jest licznik referencji, bez niego często będziesz miał wycieki lub podwójne zwalnianie. Dodatkowo jawne zwalnianie nie gra zbyt dobrze z wyjątkami (min. nie ma klauzuli finally, nie mówiąc już o wyjątkach w konstruktorach).

0

Mam pytanie, skoro te wskaźniki są w standarcie to gdzie znajdę ich dokumentacje? Szukałem na cplusplus.com i http://en.cppreference.com/w/cpp bez skutku.
Czy chodzi o te?
http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/smart_ptr.htm
Jakie są jeszcze sprytne wskaźniki których nie ma w boost?

  1. auto_ptr
  2. ?
1

auto_ptr jest już chyba deprecated. W c++11 jest unique_ptr, shared_ptr i weak_ptr.
http://en.wikipedia.org/wiki/C%2B%2B11#Allow_garbage_collected_implementations

//edit: W menu po prawej masz resztę tych smart pointers(widzę, że jest jak w boos'cie)
http://en.cppreference.com/w/cpp/memory/unique_ptr

1

@Bumcykowy - sprytne wskaźniki w standardzie są wzięte z boosta (jak wiele innych rzeczy). Auto_ptr jest w standardzie, ale od niego już lepszy jest goły wskaźnik, przekażesz auto_ptr do funkcji przez wartość, a nie przez referencję i zniszczy Ci się poprzedni obiekt, podobna jest sytuacja z kontenerami. Co do reference to ja używam: http://en.cppreference.com/ , szczególnym plusem tej strony jest podawanie złożoności obliczeniowej operacji.

0

Czyli wychodzi na to ze C++11 nie ma tylko scoped_array i shared_array o ile unique_ptr = intrusive_ptr. Czy mam racje? Których lepiej używac ? boost czy std?

1

Oczywiście, że mogą się pojawić gołe wskaźniki w projektach, które używają wskaźników inteligentnych. Nie w każdej sytuacji oczywiście. Ale jeżeli tylko coś "obserwujemy" i mamy pewność, że obiekt przeżyje nas (zostanie zwolniony dopiero po nas) to jak najbardziej.
Przykładem może być klasa węzła. Węzeł ma wektor unique_ptr-ów do swoich dzieci, a dzieci mogą posiadać goły wskaźnik do swojego rodzica. Nie ma sensu użyć inteligentnego wskaźnika, bo dzieci nie mogą przeżyć swoich rodziców, więc nie mogą być w żadnym stopniu odpowiedzialne za ich zwolnienie.

0
AAAAAaaaAAAa napisał(a):
 
MojaKlasa* klasa = new MojaKlasa();
//...coś się dzieje
delete klasa;

A czemu tworzysz ten obiekt na stercie? Ten przykład jest małorealistyczny.

0

Dlaczego mało realistyczny?

1

C++ to nie Java, obiekty których czas życia ogranicza się do funkcji powinny być alokowane na stosie.

0

Ok, to teraz głupie pytanie mega lamerskie:

Na stosie są tworzone obiekty które są zadeklarowane wewnątrz funkcji, tak?
Na stercie byłoby gdybym deklarację przeniósł bardziej globalnie tzn poza funkcję?
Prośba o szersze wytłumaczenie - wiem że to lamerstwo jak się masz.

0

Pamięć na stercie jest alokowana z użyciem operatora new. Reszta jest alokowana na stosie. Czyli ClassName objectName; znajdzie się na stosie i zostanie zwolniony po powrocie z funkcji. ClassName *objectName = new ClassName() znajdzie się na stercie i musi być zwolnione operatorem delete.

0

Super, dziękuję :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1