Давно мне хотелось выполнить итерацию карты C++ с помощью struct
вместо std::pair
. Причина этого в том, что я всегда нахожу pair.first
и pair.second
двусмысленными.
Итак, я попробовал этот код:
map< string, int > wordCounts;
wordCounts[ "a" ] = 37;
wordCounts[ "the" ] = 10;
wordCounts[ "you" ] = 5;
struct WordCountPair {
string word;
int count;
WordCountPair( const pair<const string, int>& p ) :
word( p.first ), count( p.second ) { }
};
for( WordCountPair e : wordCounts ) {
printf( "%s occurred %d times\n", e.word.c_str(), e.count );
}
Работает, правда, дороговато с теми копиями, которые происходят
Кто-нибудь знает способ сделать что-то подобное, без копирования?
«Я хотел выполнить итерацию карты C++ с помощью struct
вместо std::pair
». -- Я сомневаюсь, что это правда. Гораздо более вероятно, что вы хотели иметь более осмысленные имена для ключа и значения, чем first
и second
, и ваш план достижения этой цели состоит в том, чтобы использовать struct
вместо std::pair
(игнорируя тот факт, что std::pair<X,Y>
является struct
). Сосредоточение внимания на своей реальной цели может помочь избежать ослепления в отношении альтернативных подходов.
Смотрите этот ответ в дюпе.
Если у вас есть доступ к C++17 или новее, вы можете решить проблему с помощью структурированной привязки. Это создаст в серверной части заполнитель для возвращаемой пары, а затем предоставит вам именованные ссылки на пару с предоставленными вами именами. Это даст вам что-то вроде
for(const auto& [word, count] : wordCounts ) {
printf( "%s occurred %d times\n", word.c_str(), count );
}
const auto&
гарантирует, что внутренний объект является ссылкой на элемент карты, а затем word
и count
являются ссылками на эту парную ссылку, поэтому копий вообще не происходит.
struct WordCountPairRef {
std::string const& word;
int const& count;
WordCountPairRef( std::pair<const std::string, int> const& p ) :
word( p.first ), count( p.second ) { }
};
for( WordCountPairRef e:wordCounts )
это позволяет избежать копирования.
Обратите внимание, что это не обеспечивает соблюдение срока службы. Однако в цикле for(:)
над std::map
базовый std::pair
находится в std::map
, поэтому эти ссылки относительно безопасны.
Однако структурированные привязки — это современный идиоматический способ решения этой проблемы:
Если у вас есть доступ к C++17 или новее, вы можете решить проблему с помощью структурированной привязки. Это создаст в серверной части заполнитель для возвращаемой пары, а затем предоставит вам именованные ссылки на пару с предоставленными вами именами. Это даст вам что-то вроде
for( auto const&[word, count]:wordCounts )
это создает ссылки на word
и count
без создания структуры.
Вы можете избежать копий, используя ссылки на участников, например.