Ponieważ std::list
i std::vector
istnieją, czy istnieje powód, aby używać tradycyjnych tablic C w C ++, czy też należy ich unikać, tak jak malloc
?
Ponieważ std::list
i std::vector
istnieją, czy istnieje powód, aby używać tradycyjnych tablic C w C ++, czy też należy ich unikać, tak jak malloc
?
Odpowiedzi:
W C ++ 11 tam, gdzie std::array
jest dostępna, odpowiedź brzmi „tak, należy unikać tablic”. Przed C ++ 11 może być konieczne użycie tablic C do przydzielenia tablic w automatycznym magazynie (tj. Na stosie).
Zdecydowanie, chociaż std::array
w C ++ 11, praktycznie tylko dla danych statycznych. Tablice w stylu C mają trzy ważne zalety w stosunku do
std::vector
:
Nie wymagają alokacji dynamicznej. Z tego powodu tablice w stylu C powinny być preferowane, gdy istnieje duże prawdopodobieństwo, że masz dużo bardzo małych tablic. Powiedz coś w rodzaju punktu n-wymiaru:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
Zwykle można sobie wyobrazić, że dims
będzie to bardzo małe (2 lub 3),
T
wbudowany typ ( double
) i może mieć
std::vector<Point>
miliony elementów. Na pewno nie chcesz milionów dynamicznych alokacji 3-krotnych.
Obsługa inicjalizacji statycznej. Jest to problem tylko dla danych statycznych, gdzie coś takiego jak:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
Jest to często korzystniejsze wektor (a std::string
), gdyż unika wszystko kolejność inicjalizacji zagadnień; dane są wstępnie ładowane, zanim będzie można wykonać jakikolwiek kod.
Wreszcie, w związku z powyższym, kompilator może obliczyć rzeczywisty rozmiar tablicy z inicjatorów. Nie musisz ich liczyć.
Jeśli masz dostęp do C ++ 11, std::array
rozwiązuje pierwsze dwa problemy i zdecydowanie powinien być używany w pierwszym przypadku zamiast tablic w stylu C. Nie dotyczy to jednak trzeciego, a wymiarowanie tablicy przez kompilator zgodnie z liczbą inicjatorów jest nadal ważnym powodem, aby preferować tablice w stylu C.
int i[] = { 1, 2, 3 };
kontynuuje pracę z int i[] = { 1, 2, 3, 4 };
. array<int, 3>
należy ręcznie zmienić na array<int, 4>
.
make_array
funkcji podobnej do make_pair
itp . Nakładka kapelusza na @R. Martinho Fernandes .
std::array
w C ++ 11 [powinny być używane] praktycznie tylko dla danych statycznych”.
Nigdy nie mów „nigdy”, ale zgodzę się, że ich rola jest znacznie ograniczona przez prawdziwe struktury danych z STL.
Powiedziałbym również, że hermetyzacja wewnątrz obiektów powinna zminimalizować wpływ takich wyborów. Jeśli tablica jest prywatnym składnikiem danych, możesz ją wymieniać lub wchodzić bez wpływu na klientów swojej klasy.
Pracowałem nad systemami krytycznymi dla bezpieczeństwa, w których nie można używać dynamicznej alokacji pamięci. Pamięć zawsze musi znajdować się na stosie. Dlatego w tym przypadku użyjesz tablic, ponieważ rozmiar jest ustalany w czasie kompilacji.
std::array<T>
alokuje na stosach i zasadniczo nie ma narzutu na surową tablicę.
array
in c++
zapewnia szybką alternatywę dynamicznych rozmiarów std::vector
i std::list
. std :: array jest jednym z dodatków w c++11
. Zapewnia korzyści z kontenerów std, jednocześnie zapewniając semantykę typu agregacyjnego tablic w stylu C.
Więc z c++11
pewnością użyłbym std::array
, tam gdzie jest to wymagane, nad wektorem. Ale chciałbym uniknąć w stylu C tablicę C++03
.
Zwykle nie , nie przychodzi mi do głowy powód, dla którego miałbym używać tablic surowych, powiedzmy vectors
. Jeśli kod jest nowy .
Być może będziesz musiał uciekać się do korzystania z tablic, jeśli twoje biblioteki muszą być zgodne z kodem, który oczekuje tablic i surowych wskaźników.
vector.data()
w C ++ 11 lub &vector.front()
wcześniej.
Wiem, że wiele osób wskazuje std :: array do przydzielania tablic na stosie i std :: vector dla stosu. Ale żaden z nich nie wydaje się wspierać wyrównania obcego. Jeśli robisz dowolny kod numeryczny, na którym chcesz użyć instrukcji SSE lub VPX (wymagając odpowiednio wyrównania 128 lub 256 bajtów), tablice C nadal wydają się najlepszym rozwiązaniem.
Powiedziałbym, że tablice są nadal przydatne, jeśli przechowujesz niewielką statyczną ilość danych, dlaczego nie.
Jedyną zaletą tablicy (oczywiście zapakowanej w coś, co automatycznie zarządza jej cofnięciem alokacji w razie potrzeby), nad std::vector
którą mogę pomyśleć, jest to, że vector
nie może przekazać własności swoich danych, chyba że twój kompilator obsługuje C ++ 11 i konstruktory przenoszenia.
swap
.
Tablice w stylu C są podstawową strukturą danych, więc będą przypadki, kiedy lepiej z niej skorzystać. Jednak w przypadku ogólnym użyj bardziej zaawansowanych struktur danych, które zaokrągla rogi danych bazowych. C ++ pozwala robić bardzo interesujące i użyteczne rzeczy z pamięcią, z których wiele działa z prostymi tablicami.
std::array
s? W wielu przypadkach oba zostaną skompilowane do tego samego zestawu.
std::array
ma precyzyjnie zdefiniowaną semantykę zbudowaną na podstawie tablic statycznych.
Powinieneś używać kontenerów STL wewnętrznie, ale nie powinieneś przekazywać wskaźników do takich kontenerów między różnymi modułami, w przeciwnym razie skończysz w piekle zależności. Przykład:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
to bardzo dobre rozwiązanie, ale nie
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
Powodem jest to, że std :: string można zaimplementować na wiele różnych sposobów, ale łańcuch w stylu c jest zawsze łańcuchem w stylu C.