2017-06-05 35 views
15

Potrzebuję sposobu na inicjalizację elementów const z tablicy dla programu, nad którym aktualnie pracuję. Problemem jest to, że muszę zainicjować te elementy z funkcji, nie ma sposobu, aby to zrobić tak:C++ jak zainicjować elementy const z tablicy

const int array[255] = {1, 1278632, 188, ...}; 

ponieważ jej dużo danych muszę generować. Co próbowałem to memcpy danych do stałych const, ale to nie może działać i nie działało.

const int array[255]; 

void generateData(){ 
     for(int i = 0; i < 255; i++) { 
      initializeSomehowTo(5, array[i]); 
     } 
} 

Mam nadzieję, że rozumiesz, co próbuję, przepraszam, jeśli podwoiłem pytanie, musiałem to przeoczyć.

+5

Nie można zrobić 'const int tablica [255] = initializeMyArray()', ale jeśli użyto 'std :: array', można zrobić' const std :: tablicę = initializeMyArray() ' – Justin

Odpowiedz

17

Co powiesz na to?

#include <array> 
typedef std::array<int, 255> Array; 

const Array array = generateData(); 

Array generateData(){ 
    Array a; 
    for(int i = 0; i < a.size(); i++) { 
     initializeSomehowTo(a[i]); 
    } 
    return a; 
} 
+0

działa to świetnie, jedyną rzeczą jest to, że ** const int array [10] [10] [10]; ** wygląda naprawdę przerażająco: ** const std :: array , 10 >, 10> Array; ** ;-) – Tsoj

6

Najprostszym rozwiązaniem jest, aby uzyskać pełen wachlarz z funkcji i używać, aby zainicjować const (lub constexpr) obiekt. Jednak wbudowane tablice nie mogą być kopiowane, ale std::array<T, N> być:

std::array<T, 255> array = initializeData(); 

Jeśli potrzebujesz wbudowany w tablicę, mogę sobie wyobrazić, inicjowanie static członek klasy (szablonu, faktycznie) gdzie indeks jest rozszerzony z indeksów rozszerzonych z std::make_index_sequence<255> i wykorzystywane jako pozycyjnym argumentu w tablicy, to znaczy, coś wzdłuż tych linii:

#include <algorithm> 
#include <iostream> 
#include <iterator> 
#include <utility> 

int some_function(std::size_t i) { return i; } 

template <typename> struct initialized_array_base; 
template <std::size_t... I> 
struct initialized_array_base<std::index_sequence<I...>> { 
    static const int array[sizeof...(I)]; 
}; 

template <std::size_t... I> 
int const initialized_array_base<std::index_sequence<I...>>::array[sizeof...(I)] 
    = { some_function(I)... }; 

struct initialized_array 
    :initialized_array_base<std::make_index_sequence<256>> { 
}; 

int main() { 
    std::copy(std::begin(initialized_array::array), 
       std::end(initialized_array::array), 
       std::ostream_iterator<int>(std::cout, " ")); 
    std::cout << '\n'; 
} 
+4

Wow, który wygląda przerażająco na tak proste zadanie ;-) – zett42

3

można utworzyć zapisu tablicę, zainicjować, a następnie utworzyć const odniesienia do niej .

int arry[255]; 

void generateData(){ 
    for(int i = 0; i < 255; i++) { 
     initializeSomehowTo(5, arry[i]); 
    } 
} 

const int (&array)[255] = arry; 
+0

To nie powstrzymuje 'arry' przed modyfikacją, prawda? – Arun

+0

Myślę, że możesz również std :: static_cast do const reference –

+0

Dodatkowy poziom indirect (dla zmiennej referencyjnej, która również ma pamięć statyczną) może nie optymalizować się. ** Zdecydowanie nie zalecałbym korzystania z tego **, ponieważ zwracanie 'std :: array <>' z funkcji inicjalizującej pozwala uniknąć jakichkolwiek wad wydajności. –