2016-08-16 3 views
3

У меня есть контейнер struct, который содержит набор элементов конфигурации.Каков правильный способ инициализации контейнеров const с разными значениями?

struct config 
{ 
    const std::vector<int> config_items; 
    const std::vector<double> another_items; 
} 

Кроме того, у меня есть «контейнер» контейнеры, которые должны проводить известное и ограниченное количество экземпляров этих контейнеров конфигурации (например, 3). Каждый экземпляр config должен иметь разные int s и double s в соответствующем vector s.

struct setup 
{ 
    const std::vector<config> items; 
} 

все пункты, vector S'должны быть const, потому что они должны быть определены один раз и никогда не изменится.

Поскольку vector s являются const, я могу инициализировать их только в списке инициализаторов конструктора. Но я хочу иметь несколько экземпляров с разными значениями.

Я мог бы создать дочерний элемент struct s для создания каждой конфигурации в дочерних конструкторах. Но это не работает, потому что я не могу инициализировать родительский элемент в детском конструкторе:

struct config_1 : public config 
{ 
    config_1() : config_items { 1, 2 }, another_items { 1.0, 2.0 } {} // Doesn't work 
} 

Это, кажется, очень плохое решение тоже (удалить const, сделать копии ...):

struct config 
{ 
    std::vector<int> config_items;  
    std::vector<double> another_items;  
} 

struct setup 
{ 
    std::vector<config> items; 
} 

void init() 
{ 
    config c; 
    c.config_items = { 1, 2 }; 
    c.another_items = { 1.0, 2.0 }; 

    setup s; 
    s.items = { c }; 
} 

Я не могу сделать ни одного инициализатора-лист конструктор тоже, потому что у меня есть несколько vector S:

struct config 
{ 
    config(std::initializer_list<int> i, std::initializer_list<double> d); // No go 
    std::vector<int> config_items;  
    std::vector<double> another_items;  
} 

Справочная информация: Я хочу иметь зашиты const (возможно, он находится в разделе DATA или даже во флэш-памяти) для моего встроенного приложения. Не нужно читать вещи из любых файлов конфигурации и т. Д.

Итак, мой вопрос: что бы вы предложили мне, как я должен создать такой контейнер конфигурации const?


EDIT

В std::vector s фактически здесь не так. Я использую пользовательский контейнер, который хранит данные в экземпляре, например std::array, а не как std::vector, который выделяет хранилище в куче.

Так среда должна скорее выглядеть следующим образом:

struct config 
{ 
    const std::array<int, 2> config_items; 
    const std::array<double, 2> another_items; 
} 

struct setup 
{ 
    const std::array<config, 3> items; 
} 
+6

[FYI] векторы являются динамическими, поэтому их необходимо инициализировать во время выполнения. Если вам нужны статические данные, вам следует рассмотреть возможность использования 'std :: array'. – NathanOliver

+0

@NathanOliver, спасибо за этот совет. 'vector' только для простоты здесь, мы используем наши собственные шаблонные контейнеры с внутренним хранилищем данных. – dymanoid

ответ

0

После некоторых исследований я решил ответить на мой собственный вопрос.

В NathanOliver и ЧПП упоминалось, std::vector ы, используемые в вопросе выделения памяти в куче. Фактически, я использую пользовательский контейнер, похожий на std::array, который хранит данные в самом экземпляре.

Так что я должен был бы написать что-то подобное в вопросе:

struct config 
{ 
    const std::array<int, 2> config_items; 
    const std::array<double, 2> another_items; 
} 

struct setup 
{ 
    const std::array<config, 3> items; 
} 

Теперь, так как эти struct s являются PODs, я могу использовать aggregate initialization из них:

setup instance 
{ 
    // std::array c++11-ish double-braces aggregate initialization 
    // this is the items member 
    { { 
     { 
      // this is the config_items member 
      { { 1, 2 } }, 

      // this is the another_items member 
      { { 1.0, 2.0 } }, 
     }, 

     { 
      { { 3, 4 } }, 
      { { 3.0, 4.0 } }, 
     }, 

     { 
      { { 5, 6 } }, 
      { { 5.0, 6.0 } }, 
     } 
    } } 
}; 

Теперь я имеют инициализированную структуру instance, членами которой являются const, и нет кода времени выполнения для инициализации (без кодов, вызовов методов), а исходные данные будут непосредственно сохранены в DATA (по умолчанию). Это именно то, что мне нужно.

1

Вы можете сделать что-то вроде этого:

struct config 
{ 
    const std::vector<int> config_items = []{ 
     std::vector<int> retval; 
     //put whatever stuff you want in retval 
     return retval; 
    }(); 
} 

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

Обратите внимание, что std::vector будет использовать память кучи, поэтому данные никогда не войдут во флэш-память (кроме чрезвычайно агрессивного компилятора, делающего магию), поэтому вам, вероятно, понадобится std::array.

+0

Я не понял этого: как мне создать 3 экземпляра 'config', содержащих разные' config_items'? – dymanoid

+0

@dymanoid Вам нужно будет вернуть конфигурацию, а не только вектор. Вы считали, что собираетесь с 'const config', который содержит не' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' – nwp

2

может просто просто использовать такую ​​конструкцию?

struct config 
{ 
    const std::vector<int> _a; 
    config(const std::vector<int> &a): _a(a) {} 
}; 

позже где-то в коде:

config c1({1, 2, 3}); 
config c2({3, 4, 5, 6}); 

хорошо, давайте получить полный образец:

struct config 
    { 
     const std::vector<int> _items; 
     config(const std::vector<int> &items): _items(items) {} 
    }; 
    std::vector<config> settings; 
    settings.emplace_back(config({1, 2})); 
    settings.emplace_back(config({3, 4})); 
Смежные вопросы