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::begin및 std::end동일한 이름의 함수 또는 멤버 함수 와 불쾌하게 춤을 추습니다 .
— 유전자 Bushuyev

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

답변:


495

컨테이너의 각 요소 map<K, V>::value_type는 typedeffor 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-specifier-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.