C++의 오버로드된 산술 연산자에 가장 적합한 서명은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/118630

  •  02-07-2019
  •  | 
  •  

문제

나는 오버로드된 연산자+= 멤버 함수가 존재한다고 가정할 때 연산자+의 표준 형식이 다음과 같다고 가정했습니다.

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs) +=rhs;
}

그러나 이것이 또한 효과가 있을 것이라는 것이 나에게 지적되었습니다:

const T operator+ (T lhs, const T& rhs)
{
    return lhs+=rhs;
}

본질적으로 이 형식은 구현 본문에서 함수 호출로 임시 생성을 전송합니다.

두 매개변수에 서로 다른 타입을 사용하는 것이 조금 어색해 보이는데, 두 번째 형태에는 문제가 있는 걸까요?둘 중 하나를 선호하는 이유가 있나요?

도움이 되었습니까?

해결책

편집된 질문의 경우 첫 번째 양식이 선호됩니다.컴파일러는 반환 값을 최적화할 가능성이 높습니다(T의 생성자에 중단점을 배치하여 이를 확인할 수 있음).첫 번째 형식은 두 매개변수를 모두 const로 사용하므로 더 바람직합니다.

을 주제로 한 연구 반환 값 최적화, 예를 들어 다음 링크를 참조하세요. http://www.cs.cmu.edu/~gilpin/c++/performance.html

다른 팁

생성된 코드에 큰 차이가 있는지 잘 모르겠습니다.

이 두 가지 중에서 저는 (개인적으로) 의도를 더 잘 전달하는 첫 번째 형식을 선호합니다.이는 += 연산자의 재사용과 const&로 템플릿화된 유형을 전달하는 관용구와 관련이 있습니다.

나는 가독성을 위해 첫 번째 형식을 선호합니다.

첫 번째 매개변수가 복사되는 것을 보기 전에 두 번 생각해야 했습니다.나는 그것을 기대하지 않았습니다.따라서 두 버전 모두 효율적일 수 있으므로 읽기 쉬운 버전을 선택하겠습니다.

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs)+=rhs;
}

간결함을 원한다면 왜 안되나요?

내 첫 번째 생각은 두 번째 버전이 첫 번째 버전보다 엄청나게 빠를 수 있다는 것입니다. 참조가 스택에 인수로 푸시되지 않기 때문입니다.그러나 이는 컴파일러에 따라 크게 달라지며, 예를 들어 컴파일러가 명명된 반환 값 최적화를 수행하는지 여부에 따라 달라집니다.

어쨌든 의심스러운 경우에는 존재하지도 않고 필요하지도 않을 아주 작은 성능 향상을 선택하지 마십시오. 가장 명확한 버전, 즉 첫 번째 버전을 선택하십시오.

실제로는 두 번째가 더 선호됩니다.C++ 표준에 명시된 바와 같이,

3.7.2/2:자동 저장 기간

이름이 지정된 자동 객체에 초기화 또는 부작용이있는 파괴자가있는 경우, 블록의 끝 이전에 파괴되지 않으며 클래스 객체 또는 사본을 제외하고는 사용하지 않은 것으로 보이더라도 최적화로 제거되지 않아야합니다. 12.8에 지정된대로 제거 될 수 있습니다.

즉, 명명되지 않은 임시 개체가 복사 생성자를 사용하여 생성되기 때문에 컴파일러는 반환 값 최적화를 사용하지 않을 수 있습니다.그러나 두 번째 경우에는 명명되지 않은 반환 값 최적화가 허용됩니다.컴파일러가 명명된 반환 값 최적화를 구현하는 경우 가장 좋은 코드는 다음과 같습니다.

const T operator+(const T& lhs, const T& rhs)
{
    T temp(lhs);
    temp +=rhs;
    return temp;
}

내 생각에 둘 다 인라인 처리했다면(그냥 함수를 전달하는 것일 뿐이고 아마도 Operator+=() 함수는 라인을 벗어났기 때문일 것임) 거의 구별할 수 없는 코드 생성이 이루어질 것이라고 생각합니다.즉, 첫 번째가 더 정식입니다.두 번째 버전은 불필요하게 "귀엽다".

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top