1) Возвращение итератора - хорошая идея.Когда вы делаете это, естественным способом указать случай «не найден» является возврат итератора .end ().Недостатком является то, что абстракция имеет некоторую утечку: вызывающая сторона должна иметь возможность получить это значение .end (), чтобы сравнить его с ним для проверки ошибок, а возвращенный итератор предоставляет более богатый интерфейс, чем выlike (клиентский код не должен поиграть с увеличением и уменьшением итератора).
2) Возврат пустого вектора так же прост, как создание пустого вектора и его возврат.Создание пустого вектора = создание пустого вектора.Это то, что вы получаете - барабанная дробь - конструктор по умолчанию для векторного класса.
3) Вам не нужно и не нужно реализовывать цикл поиска самостоятельно.Стандартная библиотека уже реализует это для вас.(Существует специальная функция find
для map
с из-за различия ключа / значения. Для таких последовательностей, как list
, vector
и deque
, предпочитайте свободную функцию std::find
, которая исходит от <algorithm>
.
4) Вы должны предпочесть принимать параметры функции (когда они являются экземплярами классов, например std::string
) и возвращать данные (особенно сложные вещи, такие как вектор строк) по константной ссылке.Передача и возврат по значению подразумевает копию;иногда компилятор может оптимизировать это, но это не так надежно, как хотелось бы.Кроме того, причина, по которой вы используете C ++ в первую очередь, заключается в том, чтобы иметь такой уровень контроля над вещами, верно?Если нет, то не мучайте себя этим.
Тем не менее, вы не сможете этого сделать, если собираетесь возвращать вновь созданное значение иногда.Еще одним способом разработки интерфейса является возвращение указателя на вектор строк (обратите внимание, что арифметика указателей на них будет недействительной) внутри карты или указатель NULL, если значение не найдено.Это позволяет избежать копирования и отличает результат «не найден» от фактического пустого вектора в данных, но это означает, что клиентскому коду приходится иметь дело с нечетким необработанным указателем.
5) Наличие «возврата» в именифункции бесполезны, так как возвращение - это то, что делают функции.OTOH, это хорошая идея, чтобы называть вещи так, чтобы было понятно, почему параметры такие, какие они есть.
6) С итераторами для сложных типов часто хорошая идея установить typedefs.
Возвращение итератора так же просто, как:
typedef map<string, vector<string> >::iterator graph_iterator;
graph_iterator edges_named(const string& node_name) {
return outgoing.find(node_name);
}
Возвращение вектора строк так же просто, как:
typedef map<string, vector<string> >::iterator graph_iterator;
vector<string> edges_named(const string& node_name) {
graph_iterator it = outgoing.find(node_name);
return it == outgoing.end() ? vector<string>() : it->second;
}
Возвращение указателя так же просто, как:
typedef map<string, vector<string> >::iterator graph_iterator;
vector<string>* edges_named(const string& node_name) {
graph_iterator it = outgoing.find(node_name);
return it == outgoing.end() ? NULL : &(it->second);
}
Выбирай с умом.