범위 기반 for 루프에서 전달 참조를 사용하면 어떤 이점이 있습니까?


115

const auto&읽기 전용 작업을 수행하려면 충분합니다. 그러나 나는 부딪쳤다

for (auto&& e : v)  // v is non-const

최근에 몇 번. 이것은 나를 궁금하게 만듭니다.

그것은 몇 가지 모호한 구석 경우에 비해, 전달 참조를 사용하여 약간의 성능 향상이 있음을 가능 auto&또는 const auto&?

( shared_ptr모호한 코너 케이스에 대한 용의자)


즐겨 찾기에서 찾은 두 가지 예를 업데이트합니다 .

기본 유형을 반복 할 때 const 참조를 사용하는 단점이 있습니까?
범위 기반 for 루프를 사용하여 맵의 값을 쉽게 반복 할 수 있습니까?

질문에 집중하십시오 : 범위 기반 for 루프에서 auto &&를 사용하는 이유는 무엇입니까?


4
당신이 할 정말 "자주"를 참조?
궤도에서 가벼운 경주

2
나는 당신이 그것을보고있는 곳이 얼마나 "미쳤는지"측정 할 수있는 충분한 맥락이 당신의 질문에 있는지 잘 모르겠습니다.
궤도의 가벼운 경주

2
@LightnessRacesinOrbit 짧은 이야기 : 왜 auto&&범위 기반 for 루프에서 사용하고 싶 습니까?
Ali

답변:


94

내가 볼 수있는 유일한 장점은 시퀀스 반복기가 프록시 참조를 반환하고 상수가 아닌 방식으로 해당 참조에서 작업해야하는 경우입니다. 예를 들어 다음을 고려하십시오.

#include <vector>

int main()
{
    std::vector<bool> v(10);
    for (auto& e : v)
        e = true;
}

vector<bool>::reference에서 반환 된 rvalue가 상수 iterator가 아닌 lvalue 참조에 바인딩되지 않기 때문에 컴파일되지 않습니다 . 그러나 이것은 작동합니다.

#include <vector>

int main()
{
    std::vector<bool> v(10);
    for (auto&& e : v)
        e = true;
}

그런 사용 사례를 충족해야한다는 것을 알지 못한다면 나는 이런 식으로 코딩하지 않을 것입니다. 이 때문에 즉 나는 무상으로이 작업을 수행하지 않을 않습니다 당신이 뭘하는지 궁금해하는 원인 사람들. 그렇게했다면 이유에 대한 의견을 포함해도 괜찮습니다.

#include <vector>

int main()
{
    std::vector<bool> v(10);
    // using auto&& so that I can handle the rvalue reference
    //   returned for the vector<bool> case
    for (auto&& e : v)
        e = true;
}

편집하다

이 마지막 사례는 정말 이해하기 쉬운 템플릿이어야합니다. 당신은 루프가 항상 프록시 참조를 처리하는 알고있는 경우 auto뿐만 아니라 작동합니다 auto&&. 그러나 루프가 때때로 비 프록시 참조와 때로는 프록시 참조를 처리 할 때 auto&&선택의 해결책이 될 것이라고 생각 합니다.


3
반면에 명시적인 단점 은 없습니까? (제외하고 나는 생각하지 않는다 잠재적으로 혼란 사람들로부터 많은 가치 개인적으로 언급합니다.)
ildjarn

7
사람들을 불필요하게 혼동하는 코드를 작성하는 또 다른 용어는 혼란스러운 코드 작성입니다. 코드를 가능한 한 간단하게 만드는 것이 가장 좋지만 더 간단하지는 않습니다. 이렇게하면 버그 수를 줄이는 데 도움이됩니다. 즉, &&가 더 익숙해지면 아마도 5 년 후에 사람들은 auto && 관용구를 기대하게 될 것입니다 (실제로 해를 끼치 지 않는다고 가정). 그게 일어날 지 안 될지 모르겠어요. 그러나 단순한 것은 보는 사람의 눈에 달려 있으며, 자신보다 더 많은 것을 위해 글을 쓰는 경우 독자를 고려하십시오.
Howard Hinnant 2012 년

7
const auto&컴파일러가 실수로 시퀀스의 요소를 수정하지 않았는지 확인하는 데 도움을 주길 원할 때 선호 합니다.
Howard Hinnant

31
저는 개인적으로 auto&&시퀀스의 요소를 수정해야하는 일반 코드에서 사용하는 것을 좋아합니다 . 그렇지 않으면 auto const&.
Xeo

7
@Xeo : +1 C ++가 계속해서 진화하는 것은 자신과 같은 열성적인 사람들이 지속적으로 실험하고 더 나은 방법을 추구하기 때문입니다. 감사합니다. :-)
Howard Hinnant

26

범위 기반 루프 와 함께 auto&&또는 범용 참조 를 사용 for하면 얻은 내용을 캡처 할 수 있다는 이점이 있습니다. 대부분의 이터레이터의 경우 a T&또는 a T const&for some type을 얻을 수 있습니다 T. 흥미로운 경우는 반복기를 역 참조하면 일시적인 결과가 발생하는 경우입니다. C ++ 2011은 완화 된 요구 사항을 얻었으며 반복기가 반드시 lvalue를 산출하는 데 필요한 것은 아닙니다. 범용 참조의 사용은에서 전달하는 인수와 일치합니다 std::for_each().

template <typename InIt, typename F>
F std::for_each(InIt it, InIt end, F f) {
    for (; it != end; ++it) {
        f(*it); // <---------------------- here
    }
    return f;
}

함수 개체를 f처리 할 수 있습니다 T&, T const&그리고 T다르게. 범위 기반 for루프 의 본문이 달라야 하는 이유는 무엇 입니까? 물론, 범용 참조를 사용하여 유형을 추론 한 것을 실제로 활용하려면 그에 따라 전달해야합니다.

for (auto&& x: range) {
    f(std::forward<decltype(x)>(x));
}

물론, 사용 std::forward()은 이동할 반환 된 값을 수락한다는 의미입니다. 이런 객체가 내가 모르는 (아직?) 템플릿이 아닌 코드에서 많이 의미가 있는지 여부. 범용 참조를 사용하면 올바른 작업을 수행하기 위해 컴파일러에 더 많은 정보를 제공 할 수 있다고 상상할 수 있습니다. 템플릿 코드에서는 객체에 어떤 일이 발생해야하는지에 대한 결정을 내릴 수 없습니다.


9

나는 거의 항상 auto&&. 필요하지 않은데 왜 엣지 케이스에 물 릴까요? 입력하는 것도 더 짧아서 더 투명합니다. 를 사용하면 매번 정확히 auto&& x임을 알 수 있습니다.x*it


29
내 문제는 당신이 충분 하다면 포기하고 const있다는 것입니다 . 질문은 내가 물릴 수있는 코너 케이스를 묻는다. Dietmar 또는 Howard가 아직 언급하지 않은 코너 케이스는 무엇입니까? auto&&const auto&
Ali

2
을 사용하면 물린 방법 있습니다 auto&&. 캡처하는 유형이 루프의 본문에서 이동되어야하고 (예 :) 나중에 const&유형으로 확인 되도록 변경되면 코드가 자동으로 계속 작동하지만 이동은 복사본이됩니다. 이 코드는 매우 기만적입니다. 그러나, 당신은 명시 적으로 ... 당신이 정말 이러한 개체는 복사 이동하지 원했기 때문에 컴파일 오류가 발생합니다 컨테이너 유형을 변경 한 누구에 R 값 참조와 유형을 지정하는 경우
cyberbisson

@cyberbisson 방금 이것을 발견했습니다 : 명시 적으로 유형을 지정하지 않고 rvalue 참조를 어떻게 적용 할 수 있습니까? 같은 거 for (std::decay_t<decltype(*v.begin())>&& e: v)? 나는 더 나은 방법이 ...이 생각
제리 마

@JerryMa 그것은 당신이 무엇에 따라 달라집니다 않는 유형에 대해 알고. 위에서 언급했듯이은 auto&&"범용 참조"를 제공하므로 그 이외의 항목은보다 구체적인 유형을 제공합니다. 경우 vIS는 것으로 가정 vector, 당신은 할 수 decltype(v)::value_type&&당신이 결과 복용하여 원하는 가정 무엇을하는 operator*반복자 타입에 있습니다. decltype(begin(v))::value_type&&컨테이너 대신 반복기의 유형을 확인할 수도 있습니다 . 우리는 유형에 너무 작은 통찰력이있는 경우, 그러나, 우리는 그것을 고려해 볼 수 있습니다 단지로 갈 조금 더 명확한 auto&&...
cyberbisson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.