2017-02-12 14 views
0

Я пишу программу, которая проходит вокруг типа структуры, которую я не хочу изменять. Эта структура имеет два const членов, и выглядит следующим образом:error: unitialized member with const type C++

struct system_s { 
    std::string name; 
    std::string pkg; 
    char *const start_cmd[10]; 
    char *const end_cmd[10]; 
    bool ros; 

    bool equals(const system_s &cmp); 
}; 

структура в настоящее время хранится в карте со следующим форматом. Он является членом класса:

std::map<std::string, system_s> sys_map;

Существует еще одна временная карта. Подумайте о sys_map в качестве кеша, если хотите. Но на самом деле вам не нужно беспокоиться о том, как он используется ради этого вопроса. sys_map вызывается для добавления системы во временную карту следующим образом. Именно в методе класса:

add_system(sys_map[msg->system]); (*)

Эта функция имеет следующее определение. Это метод класса:

int add_system(const system_s &sys);

Когда (*) называется, я получаю следующее сообщение об ошибке:

system.h: In instantiation of ?std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = system_s; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, system_s> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = system_s; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::basic_string<char>]?: 
/tc_manager_node.cpp:74:41: required from here 
/system.h:26:8: error: uninitialized member ?system_s::start_cmd? with ?const? type ?char* const [10]? [-fpermissive] 
struct system_s { 
     ^
system.h:26:8: error: uninitialized member ?system_s::end_cmd? with ?const? type ?char* const [10]? [-fpermissive] 
In file included from /usr/include/c++/4.8/map:61:0, 
       from /opt/ros/indigo/include/ros/console.h:42, 
       from /opt/ros/indigo/include/ros/ros.h:40, 
       from 

/tc_manager_node.cpp:2: /USR/включать/C++/4.8/bits/stl_map.h: 469: 59: note: синтезированный метод? System_s :: system_s()? сначала требуется здесь __i = insert (__ i, value_type (__ k, mapped_type()));

Почему этот член типа system_s 'неинициализирован'? Предположительно, он уже инициализирован в sys_map. Это связано с передачей system_s в качестве ссылки в int add_system(const system_s &sys)?

+2

Члены класса 'const' должны быть инициализированы во время строительства объекта. 'start_cmd' и' end_cmd' не инициализируются. –

+0

, какой тип переменной можно перевести в 'char * const *'? У меня были проблемы с этим актерским составом. – errolflynn

+1

Где вы получаете 'char * const *' from –

ответ

1

operator[] of map (который вы вызываете с sys_map[msg->system]) имеет возможность создать новую запись, если запись в карте не найдена. Новая запись построена по умолчанию, но ваш класс не является конструктивным по умолчанию.

Чтобы исправить это, не используйте [] на карте.Вместо этого используйте find, чтобы найти запись, которую ищете.

+0

Ничего себе, это сработало! Изменил его на 'sys_map.find (msg-> system) -> second'. Придется позже устранить эту неэффективность, но она работает в крайнем случае. Спасибо, friendo – errolflynn

+1

@errolflynn помнят, что это потерпит неудачу, если элемент не найден; обычной идиомой будет 'auto item = sys_map.find (bla); if (item! = sys_map.end()) {... делать что-то с item-> second ...} ' –

+0

Некоторые части этой программы поддерживаются только в рамках C++ 03. Не знаете, как это сделать. Если я прав, ключевое слово 'auto' имеет отношение только к длительности переменной хранения. Но да, я могу, конечно, использовать std :: map :: iterator тип элемента для этого. – errolflynn

1

Как @Greg Kikola сказал, const членов должен быть быть инициализирован. Проверьте здесь, как это сделать с списками инициализаторов (Не путать с std::initializer_list): http://en.cppreference.com/w/cpp/language/initializer_list

+0

. Мое предположение состояло в том, что это было бы проблемой только в том случае, если Я попытался инициализировать переменную без инициализации 'const pointer'. Нигде в этом коде не следует ссылаться на конструктор, насколько мне известно, поскольку переменная 'struct' передается как ссылка. Это, как говорится, я явно ошибаюсь. Проблема, с которой я столкнулась, заключается в том, чтобы использовать тип 'char * const *'. Какой тип можно передать конструктору для этого? – errolflynn

+0

Вы должны построить его там, где даже передать его в качестве ссылки. – Gambit

+0

См. Ответ @ M.M – errolflynn

1

Позиция const с указателями иногда может сбивать с толку. X * const p указывает:

“p is a const pointer to an X that is non- const ”: you can’t change the pointer p itself, but you can change the X object via p. [source]

Это означает, что адрес по system_s создается с никогда не может быть изменен. Что плохо, так как вы не инициализируетесь конструктором start_cmd или end_cmd, это означает, что ни одному из 10 указателей не может быть назначен действительный адрес. Они начинаются с неинициализированных адресов и никогда не могут быть назначены ничем другим.

EDIT: Этот помет отмечен: . Нет прямого пути для инициализации массивов в C++ 03. Вы можете посмотреть на этот вопрос для некоторых обходных путей: Initializing a member array in constructor initializer Если у вас есть возможность пойти с , вы можете использовать List Initialization.

+0

Смогу ли я использовать конструктор для инициализации 'start_cmd' и' end_cmd'? Если да, то какой тип в конструкторе подходит для выполнения инициализации (желательно в списке инициализации)? Это команды, которые будут переданы в вызовы 'system()' или 'exec()'. – errolflynn

+1

@errolflynn Я отредактировал. Но нет пути прямого инициализации массивов в списке инициализации конструктора до [tag: C++ 11] Я включил ссылку с некоторыми обходными решениями. Проще всего было бы сделать 'start_cmd' и' end_cmd' неконстантными. –

+0

Спасибо. Вероятно, было бы легче, но я думаю, что я могу использовать этот метод, учитывая, что я уже начал использовать их как таковые. Переменные 'start_cmd' и' end_cmd' подлежат использованию для вызовов 'exec', что является причиной их ввода. – errolflynn