Другой вариант - использовать Splitter Guava. У него нет накладных расходов на регулярное выражение (которое вам не нужно в этом случае) и по умолчанию не отбрасывает пустые строки.
Например:
String data = "5|6|7||8|9||";
Iterable results = Splitter.on('|').split(data);
// convert to array
String[] asArray = Iterables.toArray(results, String.class);
Для получения дополнительной информации см. wiki: https://github.com/google/guava/wiki/StringsExplained
Если вы посмотрите документацию по методу erase , он возвращает итератор для элемента после того, который был удален.
Способ использовать это, чтобы присвоить возвращаемое значение вашему итератору следующим образом.
for (std::list<Ginfo>::iterator it = _actives.begin(); it != _actives.end();) {
if (! it->game->isActive()) {
delete it->game; it->game = nullptr;
it->g_thread->join();
delete it->g_thread; it->g_thread = nullptr;
it = _actives.erase(it);
}
else {
++it;
}
}
Поскольку получение возвращаемого значения из erase
переводит итератор к следующему элементу, мы должны следить за тем, чтобы не увеличивать итератор, когда это происходит.
На несвязанной ноте имена переменных, начинающиеся с подчеркивания, обычно зарезервированы для внутренних компонентов компилятора, и их следует избегать в вашем собственном коде.
Есть ли лучший способ собрать мусор?
blockquote>Да, не используйте
new,delete
или динамическую память вообще:struct Players{}; struct Game{ Game(Players&& players){} }; struct GInfo { GInfo(Players&& players_pair): game(std::move(players_pair)),g_thread(&Game::start, game){} Game game; std::thread g_thread; }; std::list<GInfo> _actives; void someLoop() { while (true) { GInfo& ginfo = _actives.emplace_back(matchPlayers()); } } void garbageCollector() { while (true) { //Since C++20 //_active.remove_if([](GInfo& i){ return !i.game.isActive();}); //Until C++20 auto IT =std::remove_if(_actives.begin(),_actives.end(), [](GInfo& i){ return !i.game.isActive();}); _active.erase(IT,_active.end()); // sleep(2); } }
быть несколько опечаток, но это идея.