2013-11-26 2 views
0

이것은 아마도 간단한 질문 일 것이지만, 이것은 내 마음을 가로 질러 온 것입니다. 이는 아래의 두 함수 사이의 차이에 관한되어 오히려 물체 T를 생성 그것을 값을 할당하고 객체를 리턴하는 대신 func_one()에서C++ 함수의 효율성?

T func_one(T obj) {  //for the purpose of this question, 
    return obj + obj; //T is a large object and has an overloaded '+' operator 
} 

T func_two(T obj) { 
    T output = obj + obj; 
    return output; 
} 

를, I는 새로운 오브젝트를 생성하지 않고 값 자체를 반환한다. T이 큰 개체 인 경우 func_one()func_two()보다 효율적입니까, 아니면 func_one()이 두 개체의 합계를 반환 할 때 T 개체를 만들 수 있습니까?

+0

이렇게 큰 개체를 추가하거나 반환하면 안됩니다. – Mikhail

+2

현대의 최적화 컴파일러는 비슷한 어셈블리를 생성합니다. 또한 RVO 및 이동 의미론을 사용하면이 작업을 가장 효율적으로 수행 할 수 있습니다. 알아야 할 유일한 길은 프로파일 링입니다. – Chad

답변

0

컴파일러는 fund_two를 func_one과 비슷한 것으로 최적화합니다. 그러면 func_one이 다른 것에 최적화 될 것입니다. 긴 이야기가 짧습니다. 걱정할 필요가 없다면 걱정할 필요가 없습니다. 그런 경우에는 걱정하지 마십시오. asm 출력을 볼 수 있습니다.

0

짧은 답변 : 우리는

긴 대답를 알 수 없습니다 : 그것은 T의 작동 방식에 매우 의존하고 컴파일러가 반환 값의 최적화를 지원합니다.

값으로 반환하는 함수는 RVO 또는 NRVO 최적화를 적용 할 수 있습니다. 이것은 복사 생성자를 제거하여 반환 값을 호출 함수에 직접 생성한다는 것을 의미합니다. 이것이 대형 객체를 값으로 반환 할 때의 문제이므로 성능면에서 상당한 이득을 얻습니다.

func_one과 func_two의 차이점은 func_one이 익명의 임시 값인 r 값을 반환한다는 것입니다. 이것은 RVO가 사소하게 사용될 수 있음을 의미합니다. func_two는 명명 된 값인 l 값을 반환하기 때문에 더 강력한 최적화 인 NRVO가 사용됩니다. 그러나 func_two는 사소한 것이므로 거의 확실하게 NRVO가 적용되며 두 기능은 기본적으로 동일합니다.

이것은 현대 또는 준 현대 컴파일러가 있다고 가정합니다. 만약 그렇지 않다면, 당신이 T를 구현 한 방법에 크게 의존 할 것입니다.

T가 이동 의미론을 가지고 있다면, 컴파일러는 대신 복사보다는 움직일 수 있습니다. 두 가지 기능 모두에 임시 변수가 있으므로이 기능을 두 기능에 모두 적용해야합니다. 그러나 func_two는 명명 된 값을 반환하기 때문에 이동 의미를 사용할 수 없습니다. 컴파일러가 결정합니다. 컴파일러가 RVO 또는 NRVO를 수행하지 않으면 이동을 의심합니다.

마지막으로, how + operator 및 = operator가 구현되는 방식에 따라 다릅니다. 예를 들어 표현 템플릿으로 구현 된 경우 fun_two는 여전히 할당을 필요로하므로 func_one은 매우 최적화 된 임시를 반환합니다.

요약 거의 모든 실용적인 맥락에서 동일합니다. 컴파일러가 매우 이상하게 작동하는 작은 윈도우에서는 func_one이 거의 보편적으로 빠릅니다.

0

현대 컴파일러는 여분의 변수가있는 버전을 (예를 들어, 반환 값 최적화라는 이름이없는) 값으로 변환 할 수 있습니다. 예를 들어 SO는 여기에 자주 질문하는 곳입니다 (예 : Why isn't the copy-constructor called when returning LOCAL variable). 따라서 이것은 걱정해야 할 오버 헤드가 아닙니다.

걱정해야 할 오버 헤드는 함수 호출 오버 헤드입니다. 추가 작업은 현대 CPU를 최대 한 번만 사용합니다.함수 호출에는 인수의 양에 따라 10 ~ 20 사이클이 소요됩니다.

질문에 T의 의미가 무엇인지 확실하지 않습니다 (템플릿 매개 변수입니까, 클래스입니까? 질문에 공개하지 않으려는 유형의 자리 표시 자입니까?). 그러나 함수 호출 오버 헤드 문제가 있는지 여부는 해당 유형에 따라 다릅니다. 그리고 컴파일러가 함수를 인라인 할 수 있는지 여부에 달려 있습니다.

  • 분명히 인라인 인 경우 함수 호출 오버 헤드가 발생하지 않습니다.
  • 만약 T이 값 비싼 operator+() 과부하가있는 복잡한 유형이라면, 당신도 괜찮습니다.
  • 그러나 T이 예를 들어 int이고 함수가 인라인되지 않은 경우 함수의 오버 헤드가 대략 90 %입니다.