Pytanie newbie - po co tablice w stylu C jak mamy std::array ?

1

std::array ma wiadome bajery i jest bezpieczniejszy od zwykłych tablic w stylu C.

Dlaczego zatem w wszelkich kursach/książkach związanych z C++ jest lekcja na ten temat skoro osoba znająca std::array" i pisząca w C++ raczej będzie na tym operować niż na tablicach w stylu C ? Czy chodzi tutaj o to,ze jeśli tworzymy oprogramowanie do np. takiego mikrokontrolera,gdzie zasoby pamięci są ograniczone i jeśli wolimy kodować w C++ to wiedza o zwykłych tablicach się przyda bo tutaj nie będziemy mogli użyć std::array ?

1

Najprostsza odpowiedź to po prostu kompatybilność. Po prostu w ten sposób można kompilować wiele linii kodu które są napisane w czystym C za pomocą nowoczesnych kompilatorów C++. Oczywiście nie każdy kod w czystym C jest poprawnym kodem C++, jednak takich przypadków jest na tyle mało, że można powiedzieć, iż większość kodu C skompilujemy bez większych zmian jako C++.

Analogicznie można zapytać dlaczego utrzymuje się podobną kompatybilność na poziomie CPU oraz jego mnemoników. Można by zaorać wszystko i zrobić lepszą i wydajniejszą architekturę procesorów kosztem zerwania z kompatybilnością, jednak nikt tego nie robi. Dzisiejsze procesory wykonają kod który został napisany na procesor 386.

0
Quanti994 napisał(a):

std::array ma wiadome bajery i jest bezpieczniejszy od zwykłych tablic w stylu C.

Dlaczego zatem w wszelkich kursach/książkach związanych z C++ jest lekcja na ten temat

Mógł podać te kursy?

Quanti994 napisał(a):

std::array ma wiadome bajery i jest bezpieczniejszy od zwykłych tablic w stylu C.

skoro osoba znająca std::array" i pisząca w C++ raczej będzie na tym operować niż na tablicach w stylu C ?

To nie jest do końca prawda, pewne podstawy trzeba znać, przykład:
Po co uczyć się wskaźników skoro są smart pointery?
Właśnie po to aby w razie czego umieć napisać własny smart pointer gdyby te z STL nie spełniały twoich wymagań.
Tak poza tym to że masz projekt w C++ nie oznacza że nie będziesz używał bibliotek zewnętrznych napisanych w C.

Quanti994 napisał(a):

std::array ma wiadome bajery i jest bezpieczniejszy od zwykłych tablic w stylu C.

Czy chodzi tutaj o to,ze jeśli tworzymy oprogramowanie do np. takiego mikrokontrolera,gdzie zasoby pamięci są ograniczone i jeśli wolimy kodować w C++ to wiedza o zwykłych tablicach się przyda bo tutaj nie będziemy mogli użyć std::array ?

std::array w lekkim uproszczeniu to wrapper na C-Style array, wydajność i zużycie pamięci w większości przypadków powinna być taka sama, zmienia się natomiast koncepcja nad czym pracujemy, tzn. instancje std::array traktujemy jako obiekt, a to oznacza że możemy go zwracać w funkcji, natomiast w C-Style array operujemy na wskaźnikach.

6

Miliony linii kodu napisano w C++ nim nadeszła wersja 11 i std::array, jako programista tego języka musisz być w stanie taki kod zrozumieć i utrzymać, nawet jeśli współczesne dobre praktyki nakazują unikać "starych" konstrukcji.

4
Quanti994 napisał(a):

std::array ma wiadome bajery i jest bezpieczniejszy od zwykłych tablic w stylu C.

Dlaczego zatem w wszelkich kursach/książkach związanych z C++ jest lekcja na ten temat skoro osoba znająca std::array" i pisząca w C++ raczej będzie na tym operować niż na tablicach w stylu C ? Czy chodzi tutaj o to,ze jeśli tworzymy oprogramowanie do np. takiego mikrokontrolera,gdzie zasoby pamięci są ograniczone i jeśli wolimy kodować w C++ to wiedza o zwykłych tablicach się przyda bo tutaj nie będziemy mogli użyć std::array ?

Bardzo dobre pytanie, szczególnie jak zadaje je początkujący. Masz 100% racji, że należy używać std::array.
Wyjaśnienie tego stanu rzeczy jest proste:

  • zwykle są to stare kursy
  • niektórzy nie potrafią zmienić przyzwyczajeń
  • 90% darmowych kursów w internecie pisane jest przez dyletantów, którzy kopiują stare kursy. Zwykle to są początkujący, którzy po nauczeniu się "hello word" konicznie chcą się dzielić swoją wiedzą.
  • jest taka mania nauczania C++ zaczynając od C, która trudno wyplenić.
0

Mam wrażenie że std::array po prostu nie bardzo się przyjęło. Tam gdzie potrzeba zgodności z C i tak używa się tablic z C, a tam gdzie nie to std::vector.

0
MarekR22 napisał(a):

Bardzo dobre pytanie, szczególnie jak zadaje je początkujący. Masz 100% racji, że należy używać std::array.
Wyjaśnienie tego stanu rzeczy jest proste:

  • zwykle są to stare kursy

Zgoda

  • niektórzy nie potrafią zmienić przyzwyczajeń

Też prawda...

[...]

Nie zawsze i nie do końca...

Uczę zarówno podstaw programowania jak i programowania obiektowego. Zastanawiałem się bardzo poważnie nad wprowadzeniem na podstawach programowania std:array jako podstawowego używanego typu "tablicowego" i po analizie wszystkich za i przeciw - zrezygnowałem... Zostałem przy zwykłych tablicach i std::vector (z mocną sugestią, żeby używali tego drugiego).

Co daje uczniowi std::array ?
a) może go przekazać do funkcji przez wartość/referencje i może go zwrócić z funkcji
b) może sprawdzić jego rozmiar
c) może dla niego uzyć operatora przypisania
d) mógłby użyć .at() zamiast [] - ale tego prawie żaden nie robi i tak ;)
Tyle, że wszystko to dostanie też w przypadku std::vector - a na etapie nauki podstaw - kwestia tego gdzie i jak dane będą alokowane nie ma najmniejszego znaczenia.

Z drugiej strony - jaki jest "koszt" użycia std::array ? Przede wszystkim to koszt nauki kompletnie nowej składni, na etapie gdzie wszystko jest nowe i niezrozumiałe. Co gorsza - jest to składnia, która potem przez długi czas do niczego innego im się nie przyda.

W przypadku wektora jest jeden "magiczny" moment - kiedy trzeba powiedzieć, że typ przechowywanych wartości wpisujemy w nawiasach trójkątnych a nie na początku jak we wszystkich innych deklaracjach.
W przypadku array - nie tylko typ ale i rozmiar (ok, to jeszcze ujdzie, w wektorze też jest inaczej niż dla zwykłej tablicy).
Tylko potem jest gorzej - funkcję do której przekazujemy wektor konkretnego typu piszemy tak jak dowolną inną funkcję. A w przypadku std::array musimy w praktyce wprowadzać od razu prawie pełną składnię szablonów.
Moim zdaniem to nie jest coś strawnego dla przeciętnego początkującego programisty. Nie mówię tu o osobach bardzo zdolnych, które trafiły na elitarne studia informatyczne. Dla typowego początkującego programisty, który na studia "okołoinformatyczne" trafił po przeciętnym liceum/technikum problemem jest napisanie już zwykłej funkcji.

Kolejna sprawa - dla początkującego programisty problemem są nawet najbardziej czytelne i oczywiste komunikaty błędów kompilatora lub linkera. W przypadku szablonów sytuacja jest już o niebo lepsza niż kilka(naście?) lat temu (kto pamięta aplikację do tłumaczenia komunikatów błędów g++ na coś bardziej zrozumiałego? ), ale... Potraficie z ręką na sercu wymienić choć jeden kompilator, który w nietrywialnym programie dla kodu generycznego ma krótkie i łatwe do zrozumienia komunikaty błędów ?

TL;DR;
Łatwo jest mówić, że atd::array jest lepszy od zwykłej tablicy, jak już się potrafi programować ;)

PS
Chętnie dam się przekonać, że nie mam racji ;)
Ten film oczywiście widziałem i z większością się zgadzam.

0

Z drugiej strony - jaki jest "koszt" użycia std::array ? Przede wszystkim to koszt nauki kompletnie nowej składni, na etapie gdzie wszystko jest nowe i niezrozumiałe. Co gorsza - jest to składnia, która potem przez długi czas do niczego innego im się nie przyda.

Jaki koszt, skoro tej składni i tak się uczy dla std::vector? Jeśli już, to kosztem kognitywnym jest konieczność pamiętania, że jedne tablice deklarujemy z [], a inne <>

0

Slyszalem ze clang jakos bardziej sensowne komunikaty bledow produkuje ale nigdy nie probowalem

2

Koncepcja tablic w C++ wywodzi się bezpośrednio z C i pamięta jeszcze lata 70 ubiegłego stulecia i nie zmieniła się znacząco w celu zachowania wstecznej kompatybilności.

Problemem tablic jest ich silny związek ze wskaźnikami (*) , gdzie nazwa tablicy jest równocześnie wskaźnikiem do pierwszego jej elementu. Komplikuje to sytuację gdyż możliwe są niejawne konwersje tablicy do wskaźnika. Dodatkowo tablica będąca "de facto" wskaźnikiem nic nie wie o swojej wielkości. To wszystko powoduje że używanie tablic bez dobrej znajomości wskaźników może doprowadzić w konsekwencji do powstania trudno wykrywalnych błędów.

(*) Dobrym przykładem jest ich przemienność

int tab[] = {1,2,3,4,5};
tab[3] = 4[tab];
// wartości tablicy zmieniają się na {1,2,3,5,5}

gdzie wywołanie tab[3] jest zamieniane przez kompilator na *(tab+3) , a 3[tab] na *(3+tab)

2

Wiecie co, ale ja np. utrzymuje około 30 letni codebase i tam tablice są a wprowadzanie czegokolwiek musi następować delikatnie. Dajmy, na to, że mamy tablicę stawek VAT, którą przekazujemy do urządzenia fiskalnego. W życiu bym nie zatrudniłbym kogoś, kto jak zobaczy taki kod to w ramach "refaktoringu", zamiast dodać kolejny element tablicy, wypierdzieli tablicę i wstawi std::array - temat na kilka godzin z testami przeradza się w pożogę, gdzie trzeba przetestować cały sterownik, uzbroić się na jakieś złe portowanie kodu z tablicy na std::array, zaparzyć melisę dla inżynierów, którzy pierwszy raz to na oczy widza na code review, a na końcu zdziwić się, że kompilator, który buduje system wcale tego nie obsługuje, bo jest z ery z przed ustaleniam jakichkolwiek standardów ... Czyli kasa wyrzucona w błoto. Taki kod się utrzymuje i co więcej - rozwija! Ludzie odchodzą, wypalają się, a ktoś musi to utrzymywać - dlatego potrzeba nowych programistów co to potrafią i tyle. Poza tym - zanim nauczysz się biegać, spróbuj chodzić. To tak jak z projektantami sieci elektrycznych - jeśli nie pracował na budowie kładąc daną sieć i punkty to będzie głupoty na papierze projektował, tak samo każdy programista C++ powinien zrozumieć i wiedzieć jak działa wskaźniki tablica i przetrenować to na zadankach, a w kodzie produkcyjnym gdzie można używać nowych struktur, ale mieć świadomość, że stare też są w użyciu i potrafić się nimi obsłużyć.

2
Bartłomiej Golenko napisał(a):

funkcję do której przekazujemy wektor konkretnego typu piszemy tak jak dowolną inną funkcję. A w przypadku std::array musimy w praktyce wprowadzać od razu prawie pełną składnię szablonów.

Że co? Nie ma pojęcia o czym piszesz, czemu w takim kontekście użycie std::array miało by być trudniejsze niż użycie std::vector?
Jedyna różnica, to stały rozmiar tablicy kontra dynamiczny rozmiar tablicy. Możesz rozwinąć?

Kolejna sprawa - dla początkującego programisty problemem są nawet najbardziej czytelne i oczywiste komunikaty błędów kompilatora lub linkera. W przypadku szablonów sytuacja jest już o niebo lepsza niż kilka(naście?) lat temu (kto pamięta aplikację do tłumaczenia komunikatów błędów g++ na coś bardziej zrozumiałego? ), ale... Potraficie z ręką na sercu wymienić choć jeden kompilator, który w nietrywialnym programie dla kodu generycznego ma krótkie i łatwe do zrozumienia komunikaty błędów ?

Tu się zgadzam, błędy kompilacji z szablonów potrafią być bardzo enigmatyczne. Ale z drugiej strony nie kojarzę, błędu z std::vector, który trudno rozszyfrować (ktoś musi używać typu elementów, które mają jakieś nietypowe ograniczenia, co w kodzie początkującego nie powinien się zdarzyć).
Viva koncepty w C++20. Problem zakręconych komunikatów błędów zniknie (ok może nie zupełnie, ale będzie dużo lepiej).

Co do std::array vs std::vector częstość wystąpień problemów, w których sztywno jest znana wielkość tablicy (i jest na tyle niewielka, że stos wystarcza) jest tak niewielka, że nie pamiętam kiedy ostatnio miałem okazję skorzystać z std::array.

1

Ha, czasami zapomina się o pewnych rzeczach.
Jak pisze testy, to najczęściej testy parametryczne (gtest). Zwykle wygląda to tak:

struct TestData {
    ....
};

const TestData testData[] {
     ...,
     ...,
};

class MyTestSuite : public testing::TestWithParam<TestData> {};

INSTANTIATE_TEST_SUITE_P(MyGroup, MyTestSuite, testing::ValuesIn(testData));

W tej sytuacji C-array jest bardziej poręczna, bo nie trzeba liczyć ile jest elementów (szczególnie jak dodaje się więcej danych testowych).
std::make_array, które by to rozwiązało to nada odległa przyszłość, a nie czuje potrzeby pisać swojej wersji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1