Rzeczy na temat C ++, które denerwują programistów C.
Pod maską dzieje się dużo magii; konstruktory, destruktory, wirtualne metody, szablony itp. mogą znacznie ułatwić i przyspieszyć pisanie kodu C ++ niż równoważny kod C, ale trudniej go zrozumieć i zrozumieć (w zależności od tego, jak dobrze znasz C ++ i związane z nim konwencje). Coś tak prostego, co Foo newFoo;
może wywoływać dużo kodu, w zależności od tego, jak Foo
zdefiniowano konstruktor klasy (i dowolne klasy, od których zależy). Dlatego konwencja polega na pisaniu ++it
zamiast na it++
iteracji przez kontener, ponieważ postfiks ++
często wymaga kosztownej operacji kopiowania.
W zależności od tego, co robisz, mogą występować pewne trywialne koszty ogólne, szczególnie w przypadku prostych zadań. Weź następujące dwa programy, pierwszy w C, drugi w C ++:
/* C version */
#include <stdio.h>
int main(void)
{
char greeting[] = "Hello, world";
printf("%s\n", greeting);
return 0;
}
/* end C version */
/* C++ version */
#include <iostream>
#include <string>
int main(void)
{
std::string greeting("Hello, world");
std::cout << greeting << std::endl;
return 0;
}
/* end C++ version */
Identyczne zachowanie, niezbyt duża różnica w zakresie źródła, ale na pudełku SLES 10, nad którym pracuję z gcc 4.1.2, pierwszy generuje plik wykonywalny o wielkości ~ 9 kb, podczas gdy drugi zajmuje 12,5 kb (bez optymalizacji ), prawie 28% większy. Typ C ++ string
jest o wiele łatwiejszy do pracy z IMO niż biblioteka ciągów C, a strumienie C ++ są o wiele bardziej elastyczne i konfigurowalne niż strumienie C, ale w przypadku tak naprawdę martwego kodu, takie mogą nie być warte narzutu.
C ++ to ogromny język w porównaniu do C, z pewną niezwykle złożoną semantyką. Osiągnięcie biegłości w posługiwaniu się C ++ zajmuje dużo więcej czasu, co oznacza, że wiele osób, które twierdzą, że znają C ++, nie zna go tak dobrze, jak im się wydaje.
Rzeczy na temat C, które denerwują programistów C ++
C nie jest bezpiecznym językiem programowania w żadnym stopniu wyobraźni; brak ograniczeń sprawdzania tablic prowadzi do wielu możliwych do wykorzystania zachowań (czy to poprzez martwą gets
funkcję, czy poprzez scanf
specyfikatory %s
i %[
). C ++ daje przynajmniej kontenery, które zgłaszają wyjątki, jeśli próbujesz uzyskać dostęp poza ich obecnie zdefiniowanym zakresem; wszystko, co daje Ci, to (jeśli masz szczęście) naruszenie segmentacji.
Zarządzanie pamięcią w C jest bardzo pracochłonne i podatne na błędy, w porównaniu do narzędzi, które udostępnia C ++. Jeśli budujesz swój własny kontener, jesteś odpowiedzialny za dopasowanie wszystkich połączeń malloc
i free
, upewnienie się, że alokacje są udane, wycofanie częściowych alokacji w przypadku błędu itp. W C ++ dodajesz elementy do lub wyjmij przedmioty z pojemnika. Jeśli wystąpi problem, zostanie zgłoszony wyjątek.
Podobnie, obsługa błędów w C jest uciążliwa w porównaniu do narzędzi udostępnianych przez C ++ (mianowicie wyjątków). Naprawdę fajne jest to, że przydzieliłeś sporo pamięci, a potem uderzyłeś w ścianę podczas przetwarzania; gdy musisz się wycofać, musisz zwolnić tę pamięć we właściwej kolejności. W przypadku zasad C ++ i RAII jest to (stosunkowo) łatwe.
Więc kiedy używam jednego nad drugim?
Jeśli to, co piszesz, jest bajecznie proste, przeczytaj je / zrób z nim / pozbądź się aplikacji, której zachowanie można opisać w kategoriach danych wejściowych i wyjściowych oraz wydajności, a następnie preferuj C niż C ++. W przeciwnym razie preferuj C ++