Я пытался вставить ключ и значения следующим образом, но получаю сообщение об ошибке:
ошибка: нет соответствующего конструктора для инициализации Edge
Я использую С++17.
Это моя программа:
#include <iostream>
#include <string>
#include <map>
struct Edge
{
int v1{};
int v2{};
Edge (int v1, int v2)
:v1{v1}, v2{v2}
{
}
};
int main()
{
std::map<std::string, Edge> mymap;
mymap["edge1"] = Edge(0,0);
mymap["edge2"] = Edge(1,1);
return 0;
}
Я почти уверен, что мой конструктор прав, но любая помощь очень ценится.
Да, это исправлено после того, как я добавил Edge() = default;, очень странно, потому что в учебнике, которому я следую, преподаватель даже не объявляет никаких конструкторов. Возможно, он использует современную версию C++20, я не уверен.
Конструктор по умолчанию создается для вас компилятором тогда и только тогда, когда вы не определили никаких других конструкторов. Как только вы объявили Edge (int v1, int v2), компилятор будет использовать только указанный вами конструктор (и конструктор синтезированной копии, но это доставит вам проблемы в другом месте)
@ tadm123 Не объявлять здесь какие-либо конструкторы было бы эквивалентно определению только конструктора по умолчанию. Так что это сработает. Поскольку вы добавили пользовательский конструктор, конструктор по умолчанию теперь не создается компилятором неявно. Отсюда и ошибка.
@ChrisMM Мне нравится этот. он настолько стар, что в ответе, получившем наибольшее количество голосов, цитируется оригинальная документация STL.
Примечание: в большинстве случаев вам не нужен конструктор по умолчанию, потому что вам нужно, чтобы параметры экземпляра имели какой-либо смысл. Лучше принудительно выполнить полную инициализацию объекта, чем добавлять тесты по всему коду, чтобы убедиться в жизнеспособности экземпляра перед его использованием. Edge достаточно прост, и вы можете (и сделали) инициализировать по умолчанию все члены разумными значениями, но даже в этом случае идеологически вам может не понадобиться конструктор по умолчанию, поскольку он отправляет неправильное сообщение пользователям, которые могут начать работать [0,0] созданные по умолчанию экземпляры и стреляют себе в ногу.





emplace():#include <iostream>
#include <string>
#include <map>
struct Edge
{
int v1{};
int v2{};
Edge() = default;
Edge(int v1, int v2) : v1{v1}, v2{v2} {}
};
int main()
{
std::map<std::string, Edge> mymap;
mymap.emplace("edge1", Edge(0, 0));
mymap.emplace("edge2", Edge(1, 1));
mymap.emplace("edge2", Edge(2, 2));
mymap.emplace("edge3", Edge(3, 3));
for (const auto &pair : mymap)
{
std::cout << pair.first << " " << pair.second.v1 << " " << pair.second.v2 << std::endl;
}
return 0;
}
Подробности emplace() можно найти по этой ссылке.
В этой ссылке более подробно объясняется вставка, emplace и оператор [] в c++.
operator[] сначала проверяет контейнер, чтобы убедиться, что элемент уже существует. Если существует, возвращается ссылка на существующий элемент. В противном случае в контейнере по умолчанию создается новый элемент и возвращается ссылка на него. Поскольку у Edge нет конструктора по умолчанию, этого не может произойти, и программа не скомпилируется. Если бы у Edge был конструктор по умолчанию, возвращаемому элементу было бы присвоено значение временного Edge, которое запрашивающий хотел вставить.
С другой стороны, Emplace() создает новый Edge «на месте» и позволяет избежать необходимости создавать временный объект и копировать или перемещать его, что немного более эффективно.
Когда вы ссылаетесь на
mymap["edge1"], система должна создать заполнитель в этом месте, но у вас нет конструктора по умолчанию. Возможно, вы захотите использоватьemplace.