2013-09-07 1 views
3

일반적으로 gcc 4.7 및 C++ 11을 사용하는 현대의 컴파일러가 언제 그리고 왜 NVRO 최적화를 적용 할 수 없는지 알고 싶습니다.현대의 컴파일러는 어떤 경우에 함수에 NRVO 최적화를 적용 할 수 없습니까?

편집 :이 코드는 실수로 로컬 변수를 반환하지 않습니다. 나는 그런

A f(A&& v) 
{ 
    return v; 
} 

로했다 다른 질문에 대한 답변을 코드의 일부 조각을보고 그들이로 변경되었다 ideone.com/APySue

참조 아래에 더 좋은 예는 @ cooky451에 의해 공급 된

A f(A&& v) 
{ 
    return std::move(v); 
} 

그들은 lvalue v에 할당 된 통과 된 값이 여전히 rvalue이고 이동 될 수 있다고 말했기 때문에. 그러나 다른 이들은 NVRO에 대한 능력을 제거 할 것이라고 썼다. 이게 뭐야? 컴파일러가 임시가 반환된다는 것을 알고 있다면 아무 것도 움직이지 않고 직접 생성 할 수 있습니까? 나는 왜 사건 하나가 NVRO를 가지지 만 사건 2가 아니라는 것을 이해하지 못한다고 생각한다. 나는 사실을 잘못해서 질문 할 수있다. 또한, 나는 그 사건 2가 이런 이유로 안티 패턴이었고 당신이 std :: move를 돌려 보내면 안된다는 것을 읽었습니다. 추가적인 통찰력이 도움이 될 것입니다. 나는 뒤에서 컴파일러가 아래와 같이 만들 것이라고 들었다 : & __hidden__은이 경우 myValue 함수에 할당된다.

A myValue = f(A()); 

// behind the scenes pseudo code for direct in place construction 

void f(A&& v, A& __hidden__) 
{ 
    __hidden__ = v; 
    return; 
} 

답변

1

불가능하기 때문에 둘 다 RVO를 사용하지 않습니다. 문제는 다음과 같습니다. & &은 여전히 ​​참고 용입니다. 반환하는 변수가 함수 - 로컬 범위 안에 있지 않습니다! 따라서 std :: move가 없으면 복사하고 이동하면 이동합니다. 당신이 이동 생성자/대입 연산자 나 완전한 전달 템플릿 코드를 작성하지 않는 한, rvalue-reference마다 뭔가를 기대하지 말라는 충고를 원합니다. 가치로 가져 가세요. 어떤 경우에는 오버 헤드가 적지 만 중요한 것은 아닙니다. 그리고 코드를 훨씬 쉽게 읽을 수 있습니다. 호출자가 인수를 복사하거나 이동할 수 있으므로 더 간단한 const오버로드를 제공 할 필요가 없습니다.

+0

나는이 예제를 간략하게 단순화했다고 생각합니다. 로컬 스택 변수가 반환되면 NVRO가 올바르게 발생 했어야합니까? – bjackfly

+0

첫 번째 경우에만 https://ideone.com/APySue를 확인하십시오. 반환 값에 std :: move를 사용하는 것이 왜 반 패턴인지 이유 중 하나입니다. 다른 하나는 RVO를 수행 할 수없는 경우 복귀를 위해 자동으로 이동이 발생한다는 것입니다. ;-) 편집 : 때로는 반환 값에 대한 std :: move는 의미가 있지만이 경우는 드뭅니다. 레퍼런스, 특히 rvalue-reference로 작업 할 때 자신을 찾았습니다. – cooky451

+0

NVRO가 첫 번째 경우에 적용될 수 있고 두 번째 경우에 적용될 수없는 이유는 내 주요 질문이라고 생각합니다. 좋은 예를 들어 더 잘 이해하기 위해 이걸 가지고 놀아 보겠습니다. – bjackfly

관련 문제