Предыдущий пост SO: Вызовы конструктора по умолчанию
Вот код:
#include <iostream>
#include <unordered_map>
using namespace std;
struct item {
std::string name;
int price;
// item() = default;
item(std::string n, int p): name(n), price(p) {}
};
void createItems(std::unordered_map<std::string, item>& blah);
int main()
{
std::unordered_map<std::string, item> blah;
createItems(blah);
cout << blah["armor"].name << " " << blah["armor"].price << std::endl;
return 0;
}
void createItems(std::unordered_map<std::string, item>& blah) {
item i1{"armor", 1000};
item i2{"amulet", 200};
blah["armor"] = i1;
blah["amulet"] = i2;
return;
}
Сообщение об ошибке при запуске:
main.cpp:20:25: required from here
/usr/include/c++/11/tuple:1824:9: error: no matching function for call to ‘item::item()’
1824 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:5: note: candidate: ‘item::item(std::string, int)’
10 | item(std::string n, int p): name(n), price(p) {}
| ^~~~
main.cpp:10:5: note: candidate expects 2 arguments, 0 provided
main.cpp:6:8: note: candidate: ‘item::item(const item&)’
6 | struct item {
| ^~~~
main.cpp:6:8: note: candidate expects 1 argument, 0 provided
main.cpp:6:8: note: candidate: ‘item::item(item&&)’
main.cpp:6:8: note: candidate expects 1 argument, 0 provided
Насколько я понимаю, вызывается конструктор по умолчанию, но, поскольку я прокомментировал строку, вызов приводит к ошибке.
Вопрос: Зачем (и где) нужен конструктор по умолчанию? Я подозреваю, что blah["armor"]
вызывает конструктор по умолчанию, но почему?
Рассмотрим выражение blah["armor"]
. Что вы ожидаете, если ключ не существует? Какой объект будет blah["armor"] = i1;
назначен, если он еще не существует? Как бы он существовал, если бы не был сконструирован по умолчанию?
Спасибо @tkausl, подумав об этом, теперь это имеет смысл.
Спасибо @molbdnilo Спасибо за объяснение. Оба комментария, а также ответ теперь имеют смысл.
Как намекнул tkausl в своем комментарии, оператору индекса нужен конструктор по умолчанию.
Что делает оператор индекса?
find tree location for key
if this location does not exist
create location
copy-construct key there
default-construct value there
return reference to value at location
Шаг 5 требует конструктора по умолчанию. И поскольку все должно быть разрешено во время компиляции, ему нужен конструктор по умолчанию, даже если вы фактически никогда не используете несуществующий ключ. (Ты, однако.)
Если у вас нет конструктора по умолчанию, вы не можете использовать оператор индекса. Используйте insert
, emplace
или try_emplace
для добавления элементов на карту и find
или at
для их поиска.
Спасибо за объяснение, помечено как ответ.
My suspicion is that blah["armor"] calls the default constructor
да.but why?
Что еще делать, если ключа нет на карте?