Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Deklaracja tablicy string o rozmiarze zmiennej

Ostatnio zmodyfikowano 2014-10-07 13:54
Autor Wiadomość
kubawal
» 2014-09-24 12:42:00
C/C++
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
P-117417
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ę.
P-117794
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ę.
C/C++
int zmienna = 5;
string nazwaA[ zmienna ];
zmienna = 100;
string nazwaB[ zmienna ];
P-117797
b00rt00s
» 2014-09-30 13:41:59
@maly: I co to zmienia?

C/C++
#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.
P-117798
maly
» 2014-09-30 13:56:52
I co to zmienia?
To że takie tablice alokowane są na stosie przed wejściem do funkcji a nie w czasie jej działania.

Kompiluje się na gcc
To jest nie standardowe rozszerzenie gcc, na innych kompilatorach zgodnych ze standardem C++ nie zadziała.
P-117801
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...
P-117803
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ń :)
P-117805
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.
P-118051
1 « 2 »
Poprzednia strona Strona 2 z 2