2013-03-10 10 views
3

나는대로 만든 Integer 클래스 이진 + 오버로드를 시도했다 :반환 객체의 두 가지 형태의 차이점은 무엇입니까?

const Integer operator+(const Integer& left,const Integer& right) 
{ 
    return Integer(left.i + right.i); 
} 

내가 첫 번째 경우에 일시적으로 Integer 객체가 생성되고 반환되며이었다 배운 것을 이제
const Integer operator+(const Integer& left,const Integer& right) 
{ 
    Integer tmp(left.i + right.i); 
    return tmp; 
} 

두 번째 경우에는 생성자 호출을 사용하여 일반적인 객체를 생성 한 다음 복사 한 다음 소멸자를 호출합니다. Ecekl이 첫 번째로 말한 것은 컴파일러가 객체를 외부 반환 값의 위치에 직접 구축함으로써 이것을 이용한다는 것입니다. 우리는 이것을 어떻게 추론합니까? 반환 값 최적화에 대해 읽었지 만 위치 정보에 직접 복사하여 의미하는 바를 얻을 수 없습니다.

+1

관련이 하나 개의 인수를 받아들이는 생성자는 일반적으로) 어색 암시 적 변환을 방지하기 위해 explicit로 표시되기 때문에, 일반적으로 하지의 경우 , NRVO가 컴파일러에 의해 적절히 구현되었다고 제공된 것은 전혀 없습니다. – WhozCraig

+0

@WhozCraig : 사실 저는 (a + b) .g()와 같은 함수 호출을 원했습니다. 따라서 반환 값을 상수로 만들어야했습니다.이 경우 a + b는 상수 일 수 있기 때문입니다. –

답변

7

는 전혀 차이가 없으며, 대부분의 상황에서 괜찮은 컴파일러는 처음으로 두 번째 양식을 최적화합니다 - 그리고 tmp을 반환 할 때 Named Return Value Optimization (NRVO)로 복사/이동 생략을 수행합니다.

코드가 읽기 쉽도록 만들거나 유지 관리 및/또는 디버그하기가 더 쉬운 경우 두 번째 양식을 사용할 수 있습니다. 성능에 관심이 있다면 컴파일러 최적화를 해제하지 않는 한 아무 이유도 없지만 처음에는 성능에 관심이 없다고 제안 할 것입니다.

그러나 const Integer을 반환하는 것은 의미가 없습니다. 만약 값으로 복귀되기 때문에, 사용자가 아니라 반환해야 Integer 다음과 같이

최종 비로서
Integer operator + (const Integer& left, const Integer& right) 
{ 
    return Integer(left.i + right.i); 
} 

, 이것은 심지어, Integerint (통지를 수락하는 비 explicit 생성자를 가지고 제공 재기록 될 수 또한, Integer`는`const`을 ??해야`반환 모든 이유 :

Integer operator + (const Integer& left, const Integer& right) 
{ 
    return left.i + right.i; 
} 
+0

그러나 명시 적이 지 않은 생성자를 원하지 않을 수도 있습니다. 비슷한 말로,'return left.i + right.i; '가'Integer' 생성자가 표시 되더라도 사용할 수 있도록하는 제안을 읽었습니다. '명백한'. 반환 형식을 지정하는 것이 충분히 명시 적이라는 이유가 있습니다. –

+1

@MatthieuM .: 좋은 지적. 동의합니다. 일반적으로 하나의 인수를 취하고 복사 생성자가 아닌 생성자는 '명시 적'으로 표시되어야합니다. 반면에,이 경우에는 (int 형을 감싸는 Integer 형), 좋은 프로그래밍 습관이라고는 할 수 없다. 제 의도는 생성자가 '명시 적'이 아니라면 OP가 명시 적 생성을 생략 할 수 있다는 사실을 중성적으로 언급하는 것이 었습니다. –

관련 문제