Ludzie, którzy są przyzwyczajeni do bezużytecznych języków, często boją się zarządzania pamięcią przez C ++. Istnieją narzędzia, takie jak auto_ptr
i, shared_ptr
które obsłużą wiele zadań zarządzania pamięcią. Wiele bibliotek C ++ poprzedza te narzędzia i ma swój własny sposób obsługi zadań zarządzania pamięcią.
Ile czasu spędzasz na zadaniach związanych z zarządzaniem pamięcią?
Podejrzewam, że jest to w dużym stopniu zależne od zestawu bibliotek, których używasz, więc powiedz, do których z nich odnosi się twoja odpowiedź, a jeśli poprawią lub pogorszą.
Odpowiedzi:
Współczesne C ++ sprawia, że nie musisz się martwić o zarządzanie pamięcią, dopóki nie będziesz musiał, tj. Dopóki nie będziesz musiał ręcznie organizować pamięci, głównie w celu optymalizacji, lub jeśli kontekst zmusi cię do tego (pomyśl o dużych ograniczeniach). Pisałem całe gry bez manipulowania surową pamięcią, martwiłem się tylko o używanie pojemników, które są odpowiednim narzędziem do pracy, jak w każdym języku.
To zależy od projektu, ale przez większość czasu nie chodzi o zarządzanie pamięcią, ale o czas życia obiektu. Zostało to rozwiązane za pomocą inteligentnych wskaźników , czyli jednego z idiomatycznych narzędzi C ++ wynikających z RAII .
Po zrozumieniu RAII zarządzanie pamięcią nie będzie stanowiło problemu.
Następnie, gdy będziesz musiał uzyskać dostęp do surowej pamięci, zrobisz to w bardzo specyficznym, zlokalizowanym i możliwym do zidentyfikowania kodzie, tak jak w implementacjach obiektów puli, a nie „wszędzie”.
Poza tego rodzaju kodem nie będziesz musiał manipulować pamięcią, a jedynie trwałość obiektów.
„Trudną” częścią jest zrozumienie RAII.
źródło
delete
ręcznie, chyba że masz jedną gównianą implementację.return
)Zarządzanie pamięcią służy do odstraszania dzieci, ale jest to tylko jeden rodzaj zasobów, którymi musi się zająć programista. Pomyśl o uchwytach plików, połączeniach sieciowych i innych zasobach uzyskanych z systemu operacyjnego.
Języki, które obsługują wyrzucanie elementów bezużytecznych, zwykle nie tylko ignorują istnienie tych zasobów, ale także utrudniają ich prawidłowe obsługiwanie, ponieważ nie zapewniają destruktora.
Krótko mówiąc, sugerowałbym, aby nie poświęcić dużo czasu programistom C ++ na martwienie się o zarządzanie pamięcią. Jak wskazuje odpowiedź klaim , kiedy już opanujesz RAII, reszta to tylko refleks.
źródło
finalize
konstrukcję. Nie wiesz jednak, kiedy zostanie on wywołany. Czy to nastąpi zanim zabraknie gniazd lub obiektów WebResponse? Znajdziesz mnóstwo artykułów, które mówią ci, że nie powinieneś polegaćfinalize
- z uzasadnionego powodu.Prawie żaden. Nawet stare technologie, takie jak COM, możesz pisać niestandardowe programy usuwające standardowe wskaźniki, które przekonwertują je w bardzo krótkim czasie. Na przykład
std::unique_ptr
można przekonwertować, aby unikatowo przechowywać odwołanie COM z pięcioma liniami niestandardowego usuwacza. Nawet jeśli musisz ręcznie napisać własną procedurę obsługi zasobów, rozpowszechnienie wiedzy takiej jak SRP i kopiowanie i zamiana sprawia, że stosunkowo łatwo jest napisać klasę zarządzającą zasobami, aby używać jej na zawsze.Rzeczywistość jest taka, że wspólny, unikalny i nieposiadający własności wszystkie są dostarczane z kompilatorem C ++ 11, a ty po prostu musisz napisać małe adaptery, aby działały nawet ze starym kodem.
źródło
Kiedy byłem programistą C ++ (dawno temu), dużo czasu martwiłem się błędem zarządzania pamięcią, próbując naprawić trudne do odtworzenia błędy .
W przypadku modemu C ++ zarządzanie pamięcią jest o wiele mniejszym problemem, ale możesz zaufać wszystkim w dużym zespole, jeśli chodzi o prawidłowe działanie. Jaki jest koszt / czas:
Więc nie chodzi tylko o czas spędzony na „ robieniu ”, to raczej problem w dużych projektach.
źródło
Często używam bibliotek boost i TR1, dzięki czemu zarządzanie pamięcią w ścisłym tego słowa znaczeniu (nowe / usuwanie) nie jest problemem. Z drugiej strony przydział pamięci w C ++ nie jest tani i należy zwrócić uwagę na to, gdzie tworzone są te fantazyjne wspólne wskaźniki. W końcu często używasz obszarów roboczych lub pracujesz z pamięcią stosu. Ogólnie rzecz biorąc, powiedziałbym, że jest to głównie problem projektowy, a nie problem implementacyjny.
źródło
ile czasu zajmuje klientowi? bardzo mało, kiedy już to zrozumiesz. kiedy kontener zarządza czasem życia i referencjami, jest to naprawdę bardzo łatwe. imo, jest to o wiele prostsze niż ręczne liczenie referencji i jest praktycznie przezroczyste, jeśli weźmiesz pod uwagę kontener, którego używasz jako dokumentację, której kompilator w wygodny sposób zapobiega przeprowadzaniu nieważnych przeniesień własności w dobrze zaprojektowanym, bezpiecznym systemie.
większość czasu, który spędzam (jako klient), zawiera typy z innych aplikacji, więc działają one dobrze w kontekście twoich programów. Przykład: to jest mój ThirdPartyFont pojemnik i obsługuje te funkcje, a zniszczenie narzędzia w ten sposób, i odniesienie licząc w ten sposób, i kopiując ten sposób, a ... . Wiele z tych konstrukcji musi być na miejscu i często jest to logiczne miejsce na ich umieszczenie. to, czy chcesz uwzględnić to jako czas, czy nie, zależy od twojej definicji (implementacja musi istnieć podczas łączenia się z tymi apis, tak?).
po tym będziesz musiał wziąć pod uwagę pamięć i własność. w systemie niższego poziomu jest to dobre i konieczne, ale może zająć trochę czasu i rusztowań, aby wdrożyć sposób przenoszenia rzeczy. nie widzę w tym bólu, ponieważ jest to wymóg systemu niższego poziomu. własność, kontrola i odpowiedzialność są oczywiste.
dzięki czemu możemy zwrócić się w stronę api opartych na c, które używają typów nieprzezroczystych: nasze kontenery pozwalają nam wyodrębnić wszystkie małe szczegóły implementacji zarządzania czasem życia i kopiowaniem tych nieprzezroczystych typów, co ostatecznie sprawia, że zarządzanie zasobami jest bardzo proste i oszczędza czas, defekty, i zmniejsza liczbę wdrożeń.
jest naprawdę bardzo prosty w użyciu - problem (pochodzący z GC) polega na tym, że musisz teraz wziąć pod uwagę czas życia swoich zasobów. jeśli pomylisz się, rozwiązanie może zająć dużo czasu. Uczenie się i integrowanie jawnego zarządzania przez całe życie jest zrozumiałe w porównaniu (nie dla wszystkich ludzi) - to prawdziwa przeszkoda. gdy czujesz się komfortowo, kontrolując czasy życia i stosując dobre rozwiązania, naprawdę bardzo łatwo jest zarządzać czasem życia zasobów. to nie jest znacząca część mojego dnia (chyba że wkradł się trudny błąd).
jeśli nie używasz kontenerów (wskaźnik automatyczny / wspólny), to po prostu błagasz o ból.
wdrożyłem własne biblioteki. Zaimplementowanie tych rzeczy zajmuje mi trochę czasu, ale większość ludzi używa ich ponownie (co zwykle jest dobrym pomysłem).
źródło
Chcesz ręcznie zwolnić pamięć, zamknąć pliki i tego rodzaju rzeczy? Jeśli tak, powiem minimum i zwykle mniej niż większość innych języków, których używałem, zwłaszcza jeśli uogólnimy to nie tylko na „zarządzanie pamięcią”, ale „zarządzanie zasobami”. W tym sensie uważam, że C ++ wymaga mniej ręcznego zarządzania zasobami niż, powiedzmy, Java lub C #.
Wynika to głównie z destruktorów, które automatyzują niszczenie zasobu (pamięci lub w inny sposób). Zazwyczaj jedyny czas, kiedy muszę ręcznie zwolnić / zniszczyć zasób w C ++, to jeśli implementuję strukturę danych na niskim poziomie (coś, czego większość ludzi nie musi robić) lub używam interfejsu API C, w którym spędzam trochę czasu pakowanie zasobu C, który należy ręcznie uwolnić / zniszczyć / zamknąć, w opakowanie C ++ zgodne z RAII.
Oczywiście, jeśli użytkownik poprosi o zamknięcie obrazu w oprogramowaniu do edycji obrazów, muszę usunąć obraz z kolekcji lub czegoś takiego. Ale miejmy nadzieję, że nie liczy się to jako zarządzanie pamięcią lub zasobami, które ma znaczenie w tym kontekście, ponieważ jest to prawie wymagane w każdym języku, jeśli chcesz zwolnić pamięć związaną z tym obrazem w tym czasie. Ale znowu wszystko, co musisz zrobić, to usunąć obraz z kolekcji, a destruktor obrazu zajmie się resztą.
Tymczasem jeśli porównam, powiedzmy, Java lub C #, często ludzie muszą ręcznie zamykać pliki, ręcznie odłączać gniazda, ustawiać odwołania do obiektów na zero, aby umożliwić ich zbieranie śmieci itp. Istnieje o wiele więcej ręcznej pamięci i zarządzanie zasobami w tych językach, jeśli mnie pytasz. W C ++ często nie potrzebujesz nawet
unlock
muteksu ręcznie, ponieważ blokada mutexów zrobi to za ciebie automatycznie, gdy muteks wyjdzie poza zakres. Na przykład nigdy nie powinieneś robić takich rzeczy w C ++:W C ++ nie trzeba robić rzeczy takich jak ręczne zamykanie plików. Ostatecznie zamykają się automatycznie, gdy tylko wyjdą poza zakres, niezależnie od tego, czy wychodzą poza zakres, czy są to zwykłe lub wyjątkowe ścieżki wykonania. Podobnie jest w przypadku zasobów związanych z pamięcią, takich jak
std::vector
. Taki kod jakfile.Close()
wyżej często byłby źle oceniany, zwłaszcza w kontekściefinally
bloku, co sugeruje, że zasoby lokalne muszą zostać uwolnione ręcznie, gdy cały sposób myślenia wokół C ++ ma to zautomatyzować.Jeśli chodzi o ręczne zarządzanie pamięcią, powiedziałbym, że C wymaga maksimum, Java / C # średnio, a C ++ minimum spośród nich. Istnieje wiele powodów, dla których należy nieco unikać używania C ++, ponieważ jest to bardzo trudny do opanowania język, ale zarządzanie pamięcią nie powinno być jednym z nich. Wręcz przeciwnie, uważam, że jest to jeden z najłatwiejszych języków w tym jednym aspekcie.
Oczywiście C ++ pozwala na ręczne przydzielanie pamięci i wywoływanie
operator delete/delete[]
ręcznie zwolnionej pamięci. Pozwala także korzystać z funkcji C, takich jakmalloc
ifree
. Ale to są praktyki kodowania w starożytnym stylu, które, jak sądzę, stały się przestarzałe na długo przed tym, zanim ludzie zaczęli przypisywać sobie uznanie, ponieważ Stroustrup opowiadał się za RAII, zanim nawet ukuł ten termin od samego początku. Więc nawet nie sądzę, że można powiedzieć, że „nowoczesne C ++” automatyzuje zarządzanie zasobami, ponieważ od początku miał to być cel. W przeciwnym razie nie można praktycznie uzyskać bezpieczeństwa wyjątkowego. Po prostu wielu mylących programistów na początku lat 90. próbowało używać C ++ jako C z obiektami, często całkowicie ignorując obsługę wyjątków i nigdy nie powinno się go używać w ten sposób. Jeśli używasz C ++ w sposób, w jaki praktycznie zawsze był przeznaczony do użycia, zarządzanie pamięcią jest całkowicie zautomatyzowane i generalnie nie jest czymś, z czym musisz sobie poradzić (lub powinieneś mieć do czynienia) w ogóle.źródło
Zależy od starszych kierowników technicznych w zespole. W niektórych firmach (w tym kopalniach) nie ma koncepcji o nazwie smart poiner. Uważa się to za fantazyjne. Tak więc ludzie po prostu umieszczają usuwanie w dowolnym miejscu, a co 2 miesiące istnieje napęd do usuwania wycieków pamięci. Nowa fala instrukcji usuwania pojawia się wszędzie. Zależy więc od firmy i ludzi, którzy tam pracują.
źródło
auto_ptr
i przyjaciółmi?