statyczna tablica a stała inicjalizowana w konstruktorze

0

Hej,
zakładam ten temat, ponieważ nie wiem już jak szukać rozwiązania następującego zagadnienia:

chcę ominąć stosowanie tablicy dynamicznej w mojej klasie w ten oto sposób:

class przyklad
{
const int stala_wielkosc //tu sobie deklaruje jakas stala

przyklad(int wielkosc): stala_wielkosc(wielkosc){...} //tu chce ja zainicjalizowac w liscie konstruktora, przy czym parametr 'wielkosc'
//sobie pobieram w innej funkcji wywolanej wczesniej :)

int tablica[stala_wielkosc]; //stala ta posluzylaby nastepnie do okreslenia wielkosci tablicy :p
}

moje pytanie brzmi: czy coś takiego jest w ogóle możliwe??
Kompilator mi mówi, że nie :) Ale może to ja coś źle robię? Bo jeśli to nie jest mozliwe, to jaki w ogóle sens mają stałe w klasie, skoro dalej nie są traktowane jak stałe?

Please pomóżcie - dopiero zaczynam się zajmować programowaniem obiektowym i nic mi nie wychodzi jak na razie :/

Pozdr

0

Kompilator ma racje i nie chodzi tu o sama stala, tylko o to, ze nie mozna w ten sposob zadeklarowac tablicy.
Jakbys jednak chcial sie "nawrocic" i uzyc dynamicznej tablicy to prosze:

class ex
{
	public:
		ex(int e): cex(e), array(new int[e]) {}
		
	private:
		const int cex;
		int *array;
	
}; 
1

@n0name_l: bez destruktora to masz piękny wyciek.

P.S. Tak przy okazji - w liście inicjalizacyjnej konstruktora nigdy nie powinno się używać pól klasy do inicjalizacji innego pola.
P.S.2 @lang: nie można tak zrobić, ponieważ rozmiar tablicy na stosie musi być znany w czasie kompilacji(pomijając rozszerzenia, które wprowadza np. gcc)

0

Ogólnie rzecz biorąc stos nie jest pamięcią dynamiczną. Rozmiar tablicy tworzonej na stosie musi być znany już na etapie kompilacji ,ponieważ gdyby napisalibyśmy np takie coś:

	int x;
        int y;
	for(int i = 0; i < 10; i++) {
		int a[i];
	}
        int z;
 

i spodziewalibyśmy się ,że na stosie zostanie utworzona po wykonaniu powyższej pętli for 9 elementowa tablica to jesteśmy w błędzie. Gdy kompilator będzie generował kod assemblerowy to już na początku musi wiedzieć o ile ma przesunąć wskaźnik stosu. Krótko mówiąc kompilator musiałby stworzyć "dynamiczną ramkę stosu" i za każdym razem jak byśmy zmieniali rozmiar alokowanej tablicy na większy rozmiar przesuwał wszystkie dalsze elementy które tkwią w ramce stosu na dalsze pozycje ,ponieważ gdyby odnosiliśmy się do jakiegoś elementu tablicy moglibyśmy "popsuć" zmienne lokalne. Moglibyśmy je po prostu nadpisać. Pomyśmy sobie ,że mamy na stosie 2000 elementową tablicę "doublów" i chcielibyśmy zmienić jej rozmiar "runtime" na większy. To może okazać się problemem gdy bezpośrednio za tą tablicą tkwi np następna tablica 1000 elementowa. Co by musiał zrobić kompilator?? przesunąć wszystkie elementy w ramce stosu na dalsze aby nie nadpisywać tej dalszej tablicy. Ciekawe jaka by była wydajność takiego rozwiązania. Takie rzeczy by szło zaimplementować w assemblerze ale nie w C++. Z tego co już powiedziałem wynika ,że na upartego wszystko się da tylko jak już wspominałem gdyby kompilator potrafił generować dynamiczne ramki stosu było by to cholernie nie wydajne. No to teraz chyba już wiesz dlaczego rozmiar tablicy tworzonej na stosie musi być stałą CZASU KOMPILACJI.

0

To jest nie do końca prawda. Po prostu standard C++ nie przewiduje tworzenia tablic na stosie, których rozmiar jest znany dopiero run time. W C jest taka możliwość, GCC wprowadza takie rozszerzenie do C++.

0

Sama koncepcja dynamicznego alokowania pamięci na stosie nie jest nowa.
http://www.kernel.org/doc/man-pages/online/pages/man3/alloca.3.html
http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
Aczkolwiek ogólnie to rozwiązanie nie jest polecane. Wykorzystanie dynamicznej alokacji na stosie ma sens, gdy potrzebujemy bardzo szybkiej alokacji oraz zwolnienia dość małego kawałka pamięci albo z jakiś powodów koniecznie potrzebujemy kawałek pamięci, który zostanie automatycznie zwolniony przy wyjściu z funkcji.

2

Ech, ten temat zawsze flejma zaczyna.

  1. Taka konstrukcja jest prawidłowa w C. Nie, nie ważne że pod Visualem nie działa. Microsoft jasno potwierdza, że kompilatora C nie będzie rozwijał.
  2. Oznacza to również, że „da się”. Nieprawdziwe są zatem gdybania że „skąd kompilator miałby wiedzieć” i tym podobne.
  3. W standardzie C++ nie jest to póki co przewidziane. Gdzieś czytałem że była taka propozycja, ale nie przeszła.
  4. Co najmniej dwa kompilatory (GCC i Clang) pozwalają na takie tablice zarówno w C jak i C++. Zresztą dlaczego nie – skoro funkcjonalność jest już dla C, to zezwolenie na jej użycie w C++ już „nic nie kosztuje”.

gdyby napisalibyśmy np takie coś

        int x;
        int y;
        for(int i = 0; i < 10; i++) {
                int a[i];
        }
        int z; 

To (dla kompilatora obsługującego VLA) oznacza dokładnie to co się wydaje: za każdym przebiegiem pętli powstaje tablica o innym rozmiarze. Co prawda, optymalizator pewnie ją wywali, jak i całą pętlę, bo nic to nie robi :-)

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