C++ std::vector - coś poszło nie tak?

0

Cześć!

Temat z serii, co z tym C++ nie tak :)
Ostatnio mam chwilę czasu i bez takiego życiowego pośpichu, analizuję sobie biblioteki dostarczane w różnych jezykach programowania.
W jednym jest coś fajnego, a w drugim co innego jest fajnego i tak sobię kontempluję nad każdą pierdołą.

1. Nic Ci nie dam
Osoba, która zna asemblera, może się troszke zdziwić, że pop np. w std::vector nic nie zwraca... Dlaczego?
Logiczne jest, że jeżeli push coś wrzuca na koniec, to pop powinien to coś ściągnąć z tego końca.
Dość długo programowałem w asm i pop nic nie zwracający to jak dom bez drzwi i okien.
Taki odpowiednik asemblerowego pop'a pojawił się np. w QList jako takeLast, a w QVector nie ma.

**2. Poprawnie nazwę, ale nie dokończę **
Z tym wrzucaniem i ściąganiem - to taki stos... ale dlaczego są metody push_back, pop_back a nie ma push_front, pop_front?
Komuś się chciało dopisać _back a analogicznego _front już nie?
W Qt w wektorach pop_front, push_front zostały dodane.

Powracając na chwilkę do pkt1, metody pop w Qt nic nie zwracają.
Zostało tak ze względu na wektory z C++?
Nie można było dopisać drugiego np. pop_front'a żeby zwracał element?

Uważam, że wektorom w C++ (a także w Qt) dużo jeszcze brakuje i tam gdzie potrzebne są dość logiczne operacje na wektorach to w std są nie zaimplementowane.
Przykładem może być projekt Octav'y, gdyby na wektorach dało się użyć operatorów arytmetycznych byłoby super - czemu nie?
Jeśli obiekty w wektorze mają operatory arytmetyczne, to czemu wektor by nie mógł przyjąć takiej operacji dla wszystkich jego elementów:

std::vector<int> vect(6, 6);
vect /= 2;
4

pop - Nie można zagwarantować poprawności przy rzuceniu wyjątku przez moze/copy constructor zwracanego obiektu.

push_front/pop_front: zobacz std::list czy std::deque :) std::vector ich nie ma, ponieważ operacje dodania/usunięcia pierwszego elementu w wektorze jest stosunkowo drogie, dlatego jeśli już się na to decydujesz to musisz użyć insert(begin())/erase(begin()). Tak samo std::forward_list nie ma std::size (ale możesz policzyć używając std::distance).

operator/= - sprawdź std::valarray ;) Ogółem imo to by było zbyt magiczne gdyby było domyślnie dostępne w kontenerach. Nawet Python czy Ruby nie definiują takich operacji dla list.

1
  1. std::vector nie jest zaprojektowany pod wyjmowanie jego pierwszego elementu. Po prostu nie do tego on służy a jeśli musisz to robić, to prawdopodobne Twój design jest zły.
  2. Faktycznie, gdyby można było stworzyć std::vector wyłącznie z intami to takie dzielenie miałoby sens.
0
pingwindyktator napisał(a):
  1. std::vector nie jest zaprojektowany pod wyjmowanie jego pierwszego elementu. Po prostu nie do tego on służy a jeśli musisz to robić, to prawdopodobne Twój design jest zły.

W niektórych przypadkach pobranie pierwszego elementu bardzo się przydaje, pomijając koszt.
Przykład?
Jeśli zaimplementuję sobię klasę w C++, która filtruje dane operując na wektorach, to podawane współczynniki A i B zwykle są na początku, przy inicjalizacji filtru.
Warto przy inicjalizacji w klasie ściągnąć pierwszy element z wektora A i trzymać w innej zmiennej jako dzielnik, lub od razu przeskalować wektory.


         N                   M
y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k)  for 1<=n<=length(x)
        k=1                 k=0

where c = a/a(1) and d = b/a(1).
0
pingwindyktator napisał(a):
  1. Faktycznie, gdyby można było stworzyć std::vector wyłącznie z intami to takie dzielenie miałoby sens.

Dlaczego tylko z intami? Można by sobie wyobrazić operatory arytmetyczne na vectorze które wykonują tę samą operację na wszystkich elementach...

y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x)

...ale cokolwiek to ma robić, to oprogramuj to a nie licz że wszystko będzie w bibliotece standardowej ;-)

0

@Azarien operatory arytmetyczne nie mają sensu na niczym poza liczbami (ewentualnie typami z user-defined-operators). Ponadto kompilator na to nie pozwoli.
http://melpon.org/wandbox/permlink/sJgDNiWAUNsLqB00
Naprawdę nie wiem jak to sobie wyobrażasz.

0

Czy ma sens czy nie, to zależy co programista chce osiągnąć i powinno się przewidzieć pewne mechanizmy.
Jeżeli elementy w wektorze można mnożyć, to wektory z tymi elementami powinny działać analogicznie.
Dla kogoś to może być magia a dla innego coś takiego jest całkiem logiczne:

    vector<complex<double>> a;
    vector<complex<double>> b;
    vector<complex<double>> c;

    a.push_back(complex<double>(1, 0));
    a.push_back(complex<double>(0, 1));

    b.push_back(complex<double>(1, 0));
    b.push_back(complex<double>(0, 1));

    c = a * b;

@Azarien nie liczę na to że wszystko ma być, ale nie oznacza to, żeby nie używać tego co jest.
Czasami nie wszystko się zna i przez to niepotrzebnie odkrywa się koło na nowo.
Chcę znów podziękować @kq, zawsze wrzuci coś o czym nie miałem pojęcia.

Do powyższego problemu, napisałem nową klasę dziedziczącą po std::vector by dodać operatory arytmetyczne, ale widzę że w std::valarray coś jest :)

1

@Otwornica
Operatory w vector operujące na liczbach to w sumie fajny pomysł, i trochę szkoda że go nie ma, mógłby czasem się przydać.

BTW. nurtuje mnie jakie są przeciwwskazania dla owych operatorów w vectorach, jeśli typ w vectorze nie będzie miał operator/, to po prostu rzuci błędem, i tyle.

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