2013-09-03 3 views
4

-O2를 사용하여 Visual Studio 또는 최신 GCC를 사용한다고 가정 해 보겠습니다. 컴파일러가 func() 안에 S을 생성 한 다음 my_result에 복사하거나 (5, 6, 5 + 6) 생성자를 사용하여 my_result을 생성하고 S 임시 생성하지 않고 생성 하시겠습니까?C++ 컴파일러는 return by value 코드를 최적화 할 예정입니까?

참고 :기능 func() 정의 및 용도는 별도의 .obj 파일입니다!

struct S 
{ 
    S(int _x, int _y, int _z) : x(_x), y(_y), z(_z) { } 
    int x, y, z; 
}; 

S func(int a, int b) 
{ 
    return S(a, b, a + b); 
} 


/// USAGE /// 

S my_result = func(5, 6); 
+0

시도해 보셨습니까? 그 결과는 무엇입니까? – viraptor

+3

그것은 컴파일러와 최적화 레벨, 플랫폼 및 모든 것에 달려 있습니다. 하지만 나는 적어도 릴리스 빌드에서이 최적화를 수행하는 괜찮은 컴파일러를 기대합니다. –

+0

@viraptor 나는이 최적화가 완료되었는지 확인하는 방법조차 모른다. – pavelkolodin

답변

7

현대 컴파일러는 종종 이러한 종류의 작업을 최적화합니다. return value optimization

+1

+1을 호출합니다. RVO 대신 Return Value Optimization을 호출하므로 링크를 클릭하지 않고 무엇인지 이해할 수 있습니다. –

0

나는 임시가 최적화되어 있는지 의심 스럽다. 생성자와 복사 생성자에 print 문을 넣고 다른 컴파일러 설정에서 인쇄 된 것을 볼 수 있습니다.

+0

print 문이 최적화를 방해합니다. –

+0

흠, 거기에 print 문을 넣으면 컴파일러는이를 최적화 할 수 없습니다. –

+0

그와는 반대로. 최적화가 활성화되면 복사 생성자가 최적화 될 가능성이 큽니다 (복사 생성자 elision 참조). 내가하지 않은 컴파일러의 품질에 대해서는 의심 스럽습니다. –

2

정의에 따르면 컴파일러와 각 애플릿 컴파일러가 선택 사항 인 것을 의미하는 최적화입니다. 확실히 어떻게 알 수 있습니까? 생성 된 코드의 디스 어셈블리를 확인하십시오!

대부분의 컴파일러는이 경우에 비교적 쉽기 때문에 (반환 값 최적화 [RVO])이 최적화를 수행해야한다고 말했습니다. 다중 반환이 없으므로 이름이 지정되지 않은 임시이므로 별칭 지정 등이 필요하지 않습니다.

1

제공되는 테스트 케이스는 RVO을 적용하기에 충분히 간단하다고 생각됩니다.

0

문제의 최적화가 관찰 가능한 차이점을 가지고 있기 때문에 직접 테스트 할 수 있습니다!

대부분의 C++ 최적화 최적화 방법은 as-if 규칙을 따르므로 검색하기가 어렵습니다. 그러나, 약간의 경우, 차이가 관찰 가능한 동작 변경을 초래하더라도, 복사 및 이동 생성자를 생략 (건너 뛰기) 할 수 있습니다.

struct S { 
    // ... 
    S(S const& o):x(o.x), y(o.y), z(o.z) { 
    std::cout << "copy ctor!\n"; 
    } 
    S& operator=(S const& o) { 
    x=o.x; 
    y=o.y; 
    z=o.z; 
    std::cout << "copy assign!\n"; 
    return *this; 
    } 
    S(S && o):x(std::move(o.x)), y(std::move(o.y)), z(std::move(o.z)) { 
    std::cout << "move ctor!\n"; 
    } 
    S& operator=(S const& o) { 
    std::tie(x,y,z) = std::tie(std::move(o.x),std::move(o.y),std::move(o.z)); 
    std::cout << "move assign!\n"; 
    return *this; 
    } 
} 

를하고 코드를 실행 :이 경우

은 S에 다음을 추가합니다. 최적화가 없으면 사본 및/또는 이동이 가능합니다.

평범하지 않은 최적화 수준에서는 RVO (및 관련 사례 인 NRVO)가 실행되어 복사본이 제거되므로 인쇄물이 사라집니다. (컴파일러가 C++ 11이 아닌 경우 위의 이동 생성자를 제거하십시오. C++ 03의 최적화가 여전히 허용됨)

C++ 11에서는 의존하지 않고 반환 값을 명시 적으로 생성 할 수 있습니다. NRVO/RVO를 return {stuff} 구문을 통해 수신합니다.

RVO (반환 값 최적화)와 NRVO (반환 값 최적화)는 상대적으로 약하다는 점에 유의하십시오. 만약 당신이 그것들에 의존한다면, 어떻게 작동하는지, 왜 깨지게하는지, 컴파일러는 구현되어있다.