std :: map과 함께 범위 기반 for () 루프를 사용하는 방법은 무엇입니까?


336

C ++ 11 범위 기반 for () 루프의 일반적인 예는 항상 다음과 같이 간단합니다.

std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
     std::cout << xyz << std::endl;
}

어떤 경우에는 xyz입니다 int. 그러나지도와 같은 것이 있으면 어떻게됩니까? 이 예제에서 변수의 유형은 무엇입니까?

std::map< foo, bar > testing = { /*...blah...*/ };
for ( auto abc : testing )
{
    std::cout << abc << std::endl;         // ? should this give a foo? a bar?
    std::cout << abc->first << std::endl;  // ? or is abc an iterator?
}

통과하는 컨테이너가 간단한 경우 범위 기반 for () 루프가 반복자가 아닌 각 항목을 제공하는 것처럼 보입니다. 좋은 점입니다 ... 반복자라면, 우리가 항상해야 할 일은 어쨌든 그것을 역 참조하는 것입니다.

그러나 나는지도와 멀티 맵과 같은 것들에 관해서는 무엇을 기대 해야하는지 혼란 스럽습니다.

(나는 여전히 g ++ 4.4를 사용하고 있지만 범위 기반 루프는 g ++ 4.6 이상이므로 아직 시도 할 기회가 없었습니다.)


4
성명서의 범위는 표준 라이브러리 std::beginstd::end동일한 이름의 함수 또는 멤버 함수 와 불쾌하게 춤을 추습니다 .
유전자 Bushuyev

10
@will 3 줄짜리 예에서, 가짜 변수 이름에 걸리고 있습니까?
Stéphane

답변:


495

컨테이너의 각 요소 map<K, V>::value_typetypedeffor std::pair<const K, V>입니다. 결과적으로 C ++ 17 이상에서는 다음과 같이 작성할 수 있습니다.

for (auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}

또는

for (const auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}

값을 수정하지 않으려는 경우

C ++ 11 및 C ++ 14에서는 향상된 for루프를 사용하여 각 쌍을 자체적으로 추출한 다음 키와 값을 수동으로 추출 할 수 있습니다.

for (const auto& kv : myMap) {
    std::cout << kv.first << " has value " << kv.second << std::endl;
}

값의 읽기 전용보기를 원하는 경우 kv변수 표시를 고려할 수도 있습니다 const.


95

C ++ 17에서는이를 구조적 바인딩 이라고 하며 다음을 허용합니다.

std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
  std::cout << k << "=" << v << "\n";
}

const &키 를 얻을 수 있지만 값에 대한 비 const 참조는 가능합니까? (map :: value_type이하는 일이기 때문에 ...)
peterchen

2
@peterchen : k것입니다 const당신이 사용하는 경우for(auto&[k,v]:testing)
및 기계는

1
구조화 된 바인딩에 cpppreference en.cppreference.com/w/cpp/language/structured_binding
TankorSmash

GCC로 컴파일하는 경우 구조적 바인딩을 위해 버전 7 이상이 필요합니다. gcc.gnu.org/projects/cxx-status.html
csknk

25

이 백서에서 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

for( type-specifier-seq simple-declarator : expression ) statement

문법적으로

{
    typedef decltype(expression) C;
    auto&& rng(expression);
    for (auto begin(std::For<C>::begin(rng)), end(std::For<C>::end(rng)); begin != end; ++ begin) {
        type-specier-seq simple-declarator(*begin);
        statement
    }
}

따라서 abc귀하의 경우에 무엇이 있을지 분명히 알 수 있습니다 std::pair<key_type, value_type >. 인쇄를 위해 다음 abc.first과 같이 하여 각 요소에 액세스 할 수 있습니다.abc.second



3

foo 및 bar의 복사 할당 연산자가 저렴하면 (예 : int, char, 포인터 등) 다음을 수행 할 수 있습니다.

foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
  cout << "Foo is " << f << " Bar is " << b;
}

4
첫 번째 코드 스 니펫은 "C ++ 11 범위 기반 for ()"를 사용하지 않습니다. "C ++ 11 : std :: map과 함께 범위 기반 for () 루프를 사용하는 방법"에 대한 대답은 아닙니다.
isoiphone

1
@ytj 그것은 답변에서 작동하지 않는다고 이미 언급되었습니다. 새로운 사용자가 시도하지 않아도 사실을 다시 찾을 필요가 없도록 제거하고 싶지 않습니다.
balki
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.