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 ++:
System.IO.StreamReader file = new System.IO.StreamReader(path);
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
...
}
finally
{
if (file != null)
file.Close();
}
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 jak file.Close()
wyżej często byłby źle oceniany, zwłaszcza w kontekście finally
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 jak malloc
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.