kubawal |
» 2014-09-24 12:42:00 int zmienna = 5; string nazwa[ zmienna ];
|
Tak nie tworzysz zwykłej tablicy, tylko VLA std::string to marnotrawstwo pamięci. |
Niekoniecznie, bo ci, którzy pisali bibliotekę standardową mogli znaleźć sposób zoptymalizowania stringa lepszy niż Twój. Poza tym std::string to (teoretycznie) tylko array znaków i jego długość, a podczas wielu operacji na c-stringach i tak potrzebujesz obliczyć jego długość Jak czytam najnowszy standard i obserwuje trendy to coraz częściej odnoszę wrażenie, że zamiast ułatwiać to on utrudnia programowanie. |
Zależy dla kogo. Jak Tobie przeszkadza najmniejsze marnotrawstwo zasobów, to lepiej pisz w C, bo z dużej ilości dorodziejstw C++11 i wyższych tak i tak nie skorzystasz :) Ad.3) Wyjątków unikam jak ognia. Moim zdaniem są one nadużywane i to trochę taki przerost formy nad treścią. |
Oj, tu się z Tobą zgadzam :) Ale wystarczy dobrze przemyśleć kod, zaadaptować go do techniki RAII i można się bez nich obejść. BTW straszny offtop się tu robi :D |
|
b00rt00s |
» 2014-09-30 12:39:07 Wracając do głównego tematu. Czegoś nie rozumiem. Sprawdziłem ten kod na dwóch kompilatorach: clang oraz gcc. Pierwszy wyrzucił błąd, a na drugim się skompilowało bezbłędnie. Swoją drogą ten błąd mnie dziwi: variable length array of non-POD element type 'std::string' (aka 'basic_string<char>') |
Dlaczego variable length? Przecież zmienna przechowująca rozmiar tablicy jest wykorzystana tylko raz, w momencie alokacji tablicy, potem przez tablicę nie jest wykorzystywana. Nawet jeśli później zmienna typu int zmieni wartość, to nie będzie to miało żadnego wpływu na zaalokowaną tablicę. |
|
maly |
» 2014-09-30 13:22:59 Nawet jeśli później zmienna typu int zmieni wartość, to nie będzie to miało żadnego wpływu na zaalokowaną tablicę. |
int zmienna = 5; string nazwaA[ zmienna ]; zmienna = 100; string nazwaB[ zmienna ]; |
|
b00rt00s |
» 2014-09-30 13:41:59 @maly: I co to zmienia? #include <iostream>
using namespace std;
int main() { int zmienna = 5; string nazwaA[ zmienna ]; zmienna = 100; string nazwaB[ zmienna ]; cout << sizeof( nazwaA ) / sizeof( string ) << endl; cout << sizeof( nazwaB ) / sizeof( string ) << endl; } Kompiluje się na gcc, po uruchomieniu wypisuje: 5 100 Wszystko jak należy. |
|
maly |
» 2014-09-30 13:56:52 To że takie tablice alokowane są na stosie przed wejściem do funkcji a nie w czasie jej działania. To jest nie standardowe rozszerzenie gcc, na innych kompilatorach zgodnych ze standardem C++ nie zadziała. |
|
b00rt00s |
» 2014-09-30 14:13:01 @maly: a to przepraszam... widać jestem niedouczony w kwestii alokacji pamięci. Swoją drogą, czasem można zgłupieć od różnic pomiędzy kompilatorami... |
|
akwes |
» 2014-09-30 14:31:26 Eh... Przed chwilą wstałem wielki post w tym temacie jednak go wcięło. Od nowa :) @b00rt00s, Sprawdziłem ten kod na dwóch kompilatorach: clang oraz gcc. Pierwszy wyrzucił błąd, a na drugim się skompilowało bezbłędnie.
|
Tylko i wyłącznie dlatego, że używasz niestandardowego rozszerzenia GCC tworząc kod niezgodny ze standardem C++ oraz kod nieprzenośny i być może trudniejszy w utrzymaniu. clang does not support the gcc extension that allows variable-length arrays in structures. This is for a few reasons: one, it is tricky to implement, two, the extension is completely undocumented, and three, the extension appears to be rarely used. Note that clang does support flexible array members (arrays with a zero or unspecified size at the end of a structure).
|
Dlaczego variable length? Przecież zmienna przechowująca rozmiar tablicy jest wykorzystana tylko raz, w momencie alokacji tablicy, potem przez tablicę nie jest wykorzystywana.
|
Variable czyli rozmiar inicjalizowany zmienną a nie zmienny rozmiar. Co więcej, zmienna może mieć wartość, na którą afektuje wiele czynników, których kompilator nie jest w stanie ustalić (inne jednostki translacji, wątki, chora arytmetyka wskaźnikowa). Przede wszystkim wartość może być dostarczana przez użytkownika. Wszystko to sprawia, że wartość zmiennej jest wiadoma dopiero w czasie wykonania. Aby kompilator mógł być pewien wartości zmiennej musi ona być const lub funkcja zwracająca wartość musi być constexpr . Dlaczego to takie ważne? 1. Tablica jest alokowana na stosie, jeżeli nie możesz mieć pewności co do jej rozmiaru to ile miejsca na stosie zarezerwujesz (rozwiązanie wymaga użycia sztuczek)? 2. Operator sizeof w kontekście VLA przestaje być wykonywany w czasie kompilacji na rzecz czasu wykonania (czyli jego semantyka staje się niespójna). Sam go zaprezentowałeś nawet o tym nie wiedząc, 3. Stos ma różne rozmiary na różnych architekturach, czasami mogą być mniejsze, czasami większe a tablicę zaalokować trzeba, 4. Musisz ciągle pamiętać o wszystkich konsekwencjach używania VLA (czyli więcej na głowie podczas czytania kodu), 5. Godzisz się na rezygnację z pewnych optymalizacji w trakcie czasu kompilacji (gdyż obliczenia są przenoszone na czas wykonania). Oczywiście, wszystko jest dla ludzi, jeżeli dokładnie wiesz co robisz, zawsze możesz to zrobić, ale musisz wiedzieć jakie są konsekwencje Twoich działań :) |
|
b00rt00s |
» 2014-10-07 13:54:09 Dziękuję za wyjaśnienie, jestem samoukiem programowania i podczas nauki przeoczyłem fakt, że zmienne na stosie są alokowane przed wejściem do zakresu. Ta jedna rzecz wyjaśnia w zasadzie wszystko. |
|
1 « 2 » |