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

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

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

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

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

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



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

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

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



답변

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

#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&&선택의 해결책이 될 것이라고 생각 합니다.


답변

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


답변

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