2015-01-16 4 views
5

Фон: Я застрял до arm-arago-linux-gnueabi-g++ (GCC) 4.3.3. Хотя ответы, требующие C++ 11 или более поздней версии, также приветствуются, явным образом выражаю любое языковое требование позже C++ 03.Как вычислить инициализацию массива const (make const look-up-tables)?

Конструктор объекта заполняет значения в таблицах, которые будут использоваться алгоритмом.

Поскольку эта таблица не изменяется и не должна изменяться, я хочу, чтобы они были const, как мне это сделать?

Сложность № 1, значения генерируются с вычислительной точки зрения, и я не хочу их жестко кодировать в исходном файле.

Сложность # 2, вычисление иногда зависит от входов, которые доступны только во время выполнения.

Сложность №3, я не знаю, почему, но я не хочу, чтобы массив был статическим, хотя значения могут быть одинаковыми для всех объектов (случаи, когда значения не зависят от ввода времени выполнения).

Сложность №4, это массив, поэтому список инициализаторов в C++ 03 не будет работать.

Edit1: Через несколько недель после того, как этот пост, я нашел как зЬй :: массив и станд :: вектор очень хорошая альтернатива массива C-типа, когда станд :: массив не доступен.

+4

Wrap массив с классом, который гарантирует, что он инициализируется только один раз, и обеспечивает только константные методы получения. – BartoszKP

+4

Наличие данных, обозначенных как «const», действительно не приносит вам никакой ценности. Вы можете изменить их в памяти, и только интерфейс возвращает ссылку на объекты const. – nothrow

ответ

3

Вы можете инкапсулировать таблицы в закрытом типе с одним экземпляром const этого типа в свой объект, а затем перенаправить соответствующие параметры конструктора в частный объект; это работает, потому что даже объект const не является const во время его строительства.

Например:

class MyClass { 
    const struct Tables { 
    double x[1000]; 
    double y[200]; 
    Tables(int i, double d) { 
     x[i] = d; 
     y[200 - i] = -d; 
    } 
    } tables; 
public: 
    MyClass(int i, double d) : tables(i, d) {} 
}; 
MyClass c(20, 5.5); 

Другой метод заключается в создании таблицы в эфемерной изменяемый массив, время жизни ограничено временем жизни конструктора, а затем инициализировать const массив из этих изменяемых массивов.

Использование C++ 11 std::array (поскольку типы массивов не может быть копия инициализирован):

class MyClass { 
    static std::array<double, 1000> buildArray(...) { 
     std::array<double, 1000> array; 
     ... // fill array 
     return array; 
    } 
    const std::array<double, 1000> mArray; 
public: 
    MyClass(...) : mArray(buildArray(...)) {} 
}; 

Обратите внимание, что std::array легко выразить в C++ 03; он не зависит от каких-либо особенностей языка C++ 11.

Если вы беспокоитесь о накладных расходах на возврат большого массива, то прибор - даже компиляторы C++ 03 способны оптимизировать большие массивы.

+0

Если я правильно понимаю, этот ответ можно суммировать как «найти/создать новый тип массива, который реализует глубокую копию через назначение», правильно ли? – user3528438

+0

@ пользователь3528438 через * initialization *. На самом деле есть лучший способ - я обновлю свой ответ. – ecatmur

+0

Я видел новый ответ. Вы пытаетесь использовать «MyClass (int i, double d): tables (i, d) {}», а не «MyClass (int i, double d): таблицы (таблицы (i, d)) {}", чтобы избежать глубокая копия структуры? – user3528438

1

Я думаю, вы могли бы реализовать класс, содержащий фактический нестрочный массив. Таким образом, вы можете легко вычислить значения в конструкторе.

Тогда этот класс должен был бы использовать только operator[] для использования в качестве массива. Или он также может просто вернуть ссылку const на массив.

Пример реализации:

#include <iostream> 
using namespace std; 

class const_array { 
    int *arr; 
    size_t size; 

public: 
    const_array(size_t size, int typ): size(size) { 
     arr = new int[size]; 
     size_t i; 
     int val = 0; 
     for (i=0; i<size; i++) { 
      val += typ; 
      arr[i] = val; 
     } 
    } 
    const_array(const const_array & src): size(src.size) { 
     arr = new int[size]; 
     size_t i; 
     for (i=0; i<size; i++) { 
      arr[i] = src.arr[i]; 
     } 
    } 
    ~const_array() { 
     delete[] arr; 
    } 

    const int * const getArray() const { 
     return arr; 
    } 
    int getSize() const { 
     return size; 
    } 

    const int& operator[](int i) { 
     return arr[i]; 
    } 
}; 

int main() { 
    const_array a(16, 4); 
    // int *arr = a.getArray(); error 
    const int *arr = a.getArray(); 
    int j = a[2]; 
    int k = arr[2]; 
    // int * pj = &(a[2]); error 
    const int * pj = &(a[2]); 
    const int * pk = &(arr[2]); 
    cout << "a[2]=" << j << " (" << pj << ") - a.getArray[2]=" 
     << j << " (" << pj << ")" << endl; 
    return 0; 
} 
+0

Не могли бы вы объяснить мне смысл третьего «const» в «const int * const getArray() const {return arr;}"? – user3528438

+0

Третий 'const' означает, что функция-член не изменяет никаких данных-членов (на самом деле это означает, что он не изменяет данные' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''' '' '' '' ''). – frasnian

+0

И в этой же строке, в чем отличие использования «const int * const» и «const int &», потому что последний позволяет «arr» как указатель, который нужно изменить? – user3528438

Смежные вопросы