Od jakiegoś czasu programuję w C ++, ale przede wszystkim koncentruję się wokół niskopoziomowych funkcji C ++. Rozumiem przez to głównie pracę ze wskaźnikami i surowymi tablicami. Myślę, że takie zachowanie jest znane jako używanie C ++ jako C z klasami. Mimo to wypróbowałem C dopiero niedawno. Byłem mile zaskoczony, jak języki takie jak C # i Java ukrywają te szczegóły w wygodnych standardowych klasach bibliotek, takich jak Słowniki i Listy.
Wiem, że standardowa biblioteka C ++ ma również wiele kontenerów, takich jak wektory, mapy i łańcuchy, a C ++ 11 dodaje do tego tylko to, że posiada std :: array i pętle dystansowe.
Jak najlepiej nauczyć się korzystać z tych nowoczesnych funkcji językowych i które są odpowiednie dla jakich chwil? Czy to prawda, że inżynieria oprogramowania w C ++ jest obecnie w większości wolna od ręcznego zarządzania pamięcią?
Na koniec, którego kompilatora powinienem użyć, aby w pełni wykorzystać nowy standard? Visual Studio ma doskonałe narzędzia do debugowania, ale nawet VS2012 wydaje się mieć straszną obsługę C ++ 11.
g++ -std=c++11
Odpowiedzi:
Po pierwsze, kilka praktycznych zasad:
Użyj
std::unique_ptr
jako inteligentny wskaźnik bez narzutów. Nie powinieneś zbyt często zawracać sobie głowy surowymi wskaźnikami.std::shared_ptr
jest również niepotrzebne w większości przypadków. Chęć współwłasności często zdradza przede wszystkim brak myślenia o własności.Użyj
std::array
do tablic o długości statycznej istd::vector
do dynamiki.Szeroko stosuj ogólne algorytmy, w szczególności:
<algorithm>
<numeric>
<iterator>
<functional>
Zastosowanie
auto
idecltype()
wszędzie tam, gdzie zwiększają czytelność. W szczególności, jeśli chcesz zadeklarować rzecz, ale takiego typu, na którym ci nie zależy, na przykład iteratora lub złożonego typu szablonu, użyjauto
. Jeśli chcesz zadeklarować rzecz pod względem rodzaju innej rzeczy, użyjdecltype()
.Uczyń wszystko bezpiecznym, gdy możesz. Kiedy masz twierdzenia, które wymuszają niezmienniki na konkretny rodzaj rzeczy, logika ta może być scentralizowana w jednym typie. A to niekoniecznie oznacza narzut związany z czasem działania. Powinno być również
(T)x
oczywiste , że należy unikać rzutów w stylu C ( ) na rzecz bardziej wyraźnych (i możliwych do przeszukiwania!) Rzutów w stylu C ++ (npstatic_cast
.).Wreszcie, dowiedz się, jak zasada trzech:
Stała się regułą piątki dzięki dodaniu konstruktora ruchu i operatora przypisania ruchu. I rozumiem ogólnie odniesienia do wartości i jak uniknąć kopiowania.
C ++ jest złożonym językiem, więc jest to trudne do scharakteryzowania, jak najlepiej wykorzystać wszystkie z nich. Ale praktyki dobrego programowania w C ++ nie zmieniły się zasadniczo w C ++ 11. Nadal powinieneś preferować kontenery zarządzane pamięcią niż ręczne zarządzanie pamięcią - inteligentne wskaźniki ułatwiają to skutecznie.
Powiedziałbym, że współczesny C ++ jest w zasadzie wolny od ręcznego zarządzania pamięcią - zaletą modelu pamięci C ++ jest to, że jest deterministyczny , a nie ręczny. Przewidywalne zwolnienia przyczyniają się do bardziej przewidywalnej wydajności.
Jeśli chodzi o kompilator, zarówno G ++, jak i Clang są konkurencyjne pod względem funkcji C ++ 11 i szybko nadrabiają swoje niedociągnięcia. Nie używam Visual Studio, więc nie mogę mówić ani za, ani przeciw.
Na koniec uwaga na temat
std::for_each
: unikaj tego w ogóle.transform
,accumulate
Ierase
-remove_if
są stare, dobre funkcjonalnemap
,fold
ifilter
. Alefor_each
jest bardziej ogólny, a zatem mniej znaczący - nie wyraża żadnych zamiarów poza zapętlaniem. Poza tym jest używany w tych samych sytuacjach, co oparte na zakresiefor
i jest syntaktycznie cięższy, nawet jeśli jest używany bez punktów. Rozważać:źródło
std::for_each
oczekiwałbym, że zakres oparty na pętli będzie lepszym zamiennikiem niż zwykłyfor
.std::for_each
, nie oparty na zakresie . Usunąłem go, aby uniknąć zamieszania.std::for_each()
. Kiedy masz lambda, jest to z pewnością lepsze niż tradycyjnafor
pętla. Zfor
pętlą opartą na zakresie, która może nie być przypadkiem, ale nie napisałeś „for
pętli opartej na zakresie ”.for
pętla” obejmuje „for
pętlę opartą na zakresie ”. Zredagowałem z dodatkowym wyjaśnieniem i przykładem do wyjaśnienia, dziękuję.Jako punkt wyjścia:
char*
ciągów znaków. Użyjstd::string
lubstd::wstring
po prostu obserwuj, jak Twój kod staje się krótszy, bardziej czytelny i bezpieczniejszy[ ]
) i użyjstd::vector
innej odpowiedniej klasy kontenera. Zaletąstd::vector
jest to, że zna swoją długość, czyści zawartość, gdy wychodzi poza zakres, łatwo ją powtarzać i powiększa się, gdy dodajesz więcej przedmiotów. Ale istnieją inne kolekcje, które mogą działać jeszcze lepiej w danych okolicznościach.std::unique_ptr
- i ucz sięstd::move
niemal natychmiast. Ponieważ może to prowadzić do pewnych noncopyable obiektów, lenistwo może czasami wysłać kierunkustd::shared_ptr
- a może masz jakieś autentyczne przypadki użycia dlastd::shared_ptr
jak dobrzeauto
gdy deklarujesz iteratory i typy, które zależą od wcześniejszych deklaracji (np. Wcześniej zadeklarowałeś wektor czegoś, teraz coś deklarujesz, użyjauto
)for_each
„surowego” dla, gdy tylko możesz, ponieważ oszczędza to innym od uważnego czytania pętli, aby dojść do wniosku, że w rzeczywistości iterujesz całą kolekcję itp. Jeśli twój kompilator obsługuje „zakres dla”, użyj gofor_each
. Dowiedz się trywialne połączeń algorytm jakiota
,generate
,accumulate
,find_if
i tak dalej.Nie przejmuj się zbytnio tym, jakiego kompilatora użyć. W „straszne, straszne” brak C ++ 11 wsparcie w VS2012 jest że nie ma o zmiennej liczbie argumentów szablony (yeah prawy, byłeś tylko o użycie zmiennej liczbie argumentów szablonów) oraz
{}
inicjator nie ma. Ja też tego chcę, ale raczej nie przestanę nad tym używać przydatnego narzędzia programistycznego.Drugą rzeczą do zrobienia, po objęciu
std::
, jest rozpoczęcie myślenia o RAII. Kiedykolwiek maszZatem masz konstruktor, szereg funkcji składowych i destruktor. Napisz zajęcia, które się tym zajmą. Być może nawet nie będziesz musiał napisać ctor i dtor. Umieszczenie
shared_ptr
zmiennej klasy jako członka jest przykładem RAII - nie piszesz kodu zarządzania pamięcią, ale gdy twoja instancja wykracza poza zakres, właściwe rzeczy się zdarzają. Rozwiń to myślenie, aby objąć takie rzeczy jak zamykanie plików, zwalnianie uchwytów, blokad itp., A kod stanie się po prostu prostszy i mniejszy (eliminując przecieki) na twoich oczach.Jeśli czujesz się naprawdę pewny siebie, oczyść się
printf
na korzyśćcout
, pozbądź się makr (#define
rzeczy) i zacznij uczyć się „zaawansowanych idiomów”, takich jak PIMPL. Mam cały kurs na ten temat w Pluralsight, który prawdopodobnie można obejrzeć, korzystając z bezpłatnego okresu próbnego.źródło
Przez programowanie. Doświadczenie to najlepszy sposób na naukę.
C ++ 11 ma wiele nowych funkcji (auto, rvalue, nowe inteligentne wskaźniki - żeby wymienić tylko kilka). Najlepiej zacząć od ich użycia i poczytać o nich, kiedy tylko możesz i kiedy znajdziesz interesujący artykuł.
To zależy od tego, co musisz zrobić. Większość aplikacji potrafi uniknąć inteligentnych wskaźników i zapomnieć o zarządzaniu pamięcią. Nadal istnieją aplikacje, które nie mogą tak łatwo uciec (na przykład, jeśli wymagają nowego umieszczenia lub niestandardowego przydziału pamięci z dowolnego powodu).
Jeśli potrzebujesz użyć Qt, będziesz musiał użyć ich reguł do zarządzania pamięcią.
Cokolwiek masz pod ręką, które obsługuje najnowszy standard:
ale żaden kompilator nie obsługuje wszystkich funkcji.
źródło
Mój uniwersytet nadal używa C ++ do nauczania. Programuję w C ++ od 5 lat, a teraz jestem studentem. Oczywiście, teraz używam dużo Java, Ruby itp. Naprawdę polecam, abyś nie spieszył się z tymi funkcjami w języku takim jak Java. Według mojego doświadczenia i opinii, po niskim poziomie funkcji C ++. Powinieneś przyjrzeć się tematom takim jak ogólne programowanie w C / C ++, takim jak tworzenie klasy szablonów, funkcje szablonów, zastępowanie operatora, metody wirtualne, inteligentne wskaźniki. W przypadku części zorientowanej obiektowo istnieje wiele funkcji C ++, a Java nie, takich jak dziedziczenie wielokrotne. Dziedziczenie jest potężne, ale także niebezpieczne. Poziom implementacji projektowania obiektowego w C ++ jest również dobrym tematem. Komunikacja między procesami, wątki są również ważne w C ++.
Dla kompilatora i debuggera. Wiem, że studio wizualne jest niesamowite. Ale naprawdę polecam uczyć się GDB, Valgrind i Make still i być dobrym w tych narzędziach. Microsoft jest niesamowity, ale zrobił dla ciebie zbyt wiele rzeczy. Jako student naprawdę musisz nauczyć się tych rzeczy, które Microsoft zrobił także tobie. Dla kompilatora G ++ jest dobry z GNU.
W końcu po tylu latach naprawdę czuję, że najważniejsze są funkcje niskiego poziomu, takie jak surowa tablica. Wektor jest naprawdę tylko dynamiczną tablicą. To są moje rekomendacje, coś może zbyt subiektywnego, po prostu weź to, co uważasz za słuszne.
źródło