pre++와 post++ 연산자 오버로딩의 차이점
int a = 0;
++ a; //前置++
a++; //后置++
"C 전문 프로그래밍"에는 다음과 같은 설명이 있습니다(P276, People's Posts and Telecommunications Press)
.
a++는 a의 주소를 가져와 그 값을 레지스터에 로드한 다음 메모리에서 a의 값을 증가시키는 것을 의미합니다.
또한 인터넷에서 연산자 오버로딩의 관점에서 차이점을 논의하는 다음과 같은 기사를 찾았습니다.
연령을 설명하는 Age 클래스가 있다고 가정합니다. 이 클래스는 연령의 자체 증가를 실현하기 위해 pre-++ 및 post-++라는 두 연산자를 오버로드합니다.
class Age
{
public:
Age& operator++() //前置++
{
++i;
return *this;
}
const Age operator++(int) //后置++
{
Age tmp = *this;
++(*this); //利用前置++
return tmp;
}
Age& operator=(int i) //赋值操作
{
this->i = i;
return *this;
}
private:
int i;
};
위의 코드에서 pre-++와 post-++ 사이에 몇 가지 차이점이 있음을 알 수 있습니다.
다른 반환 유형, 다른
형식 매개변수,
다른 코드,
다른 효율성 및
반환 값 유형의 차이
pre-++의 반환 유형은 Age&이고 post-++의 반환 유형은 const Age입니다. 즉, pre-++는 lvalue를 반환하고 post-++는 rvalue를 반환합니다. (lvalue와 rvalue에 대한 많은 논의가 있습니다. 이 문서 아래를 참조하십시오)
Lvalue와 rvalue는 pre-++와 post-++의 용도를 결정합니다.
int main()
{
Age a;
(a++)++; //编译错误
++(a++); //编译错误
a++ = 1; //编译错误
(++a)++; //OK
++(++a); //OK
++a = 1; //OK
}
++의 유형은 const Age이므로 pre-++, post-++ 및 할당과 같은 작업을 수행할 수 없습니다.
++a의 유형은 Age&이며, 물론 pre-++, post-++, 대입 및 기타 작업이 될 수 있습니다.
a++의 반환 유형이 const 객체인 이유는 무엇입니까?
두 가지 이유가 있습니다.
const 개체가 아닌 경우 a(++)++와 같은 식을 컴파일할 수 있습니다. 그러나 그 효과는 직관적이지 않습니다. 두 번째 증분은 임시 객체에 작용하기 때문에 a는 실제로 1씩만 증가합니다.
또한 내장 유형의 경우 (i++)++와 같은 표현식을 컴파일할 수 없습니다. 사용자 정의 유형에 대한 연산자 오버로드는 기본 제공 유형과 동일하게 작동해야 합니다.
a++의 반환 유형이 non-const 객체로 변경되면 분명히 컴파일을 통과하지만 이렇게 하지 않는 것이 좋습니다.
++a의 반환 유형이 참조인 이유는 무엇입니까?
그 이유는 다음과 같습니다. 내장 유형의 동작과 일치해야 합니다. ++ 앞에 추가하면 항상 증가된 개체 자체가 반환됩니다. 따라서 ++(++a)의 효과는 a가 두 번 증가한다는 것입니다.
형식 매개변수의 차이점
Pre-++에는 매개변수가 없고 Post-++에는 int 매개변수가 있지만 해당 매개변수도 사용되지 않습니다. 매우 이상합니다. 특별한 목적이 있습니까?
사실 특별한 목적은 없고 단지 문법적 제약을 우회하기 위한 것일 뿐입니다.
pre-++와 post-++의 연산자 오버로딩 함수는 서로 다른 함수 프로토타입을 가져야 합니다. 그렇지 않으면 "오버로드된 함수는 다른 함수 프로토타입을 가져야 한다"는 문법 규칙을 위반합니다.
pre-++와 post-++의 반환 유형은 다르지만 반환 유형은 함수 프로토타입에 속하지 않습니다. 문법적 제한을 우회하기 위해 포스트 ++에 int 매개변수를 추가해야 했습니다.
그 이유는 간단합니다. 실제로 다른 특별한 목적은 없습니다. 사실 앞 ++에 형식 매개변수를 추가하는 것도 가능하고, int 매개변수 대신 double 매개변수를 추가하는 것도 가능합니다. 당시에 결정된 것일 뿐입니다.
코드 구현의 차이점
앞 ++의 구현은 비교적 간단합니다.자가 증가 후 이것을 반환하십시오. 반환해야 함을 유의해야 합니다 .
Post++의 구현은 좀 더 번거롭습니다. 자동 증가 전에 개체를 반환하기를 원하기 때문에 먼저 개체를 복사한 다음 자동 증가를 수행하고 마지막으로 해당 복사본을 반환합니다.
Age의 코드에서 post ++는 pre ++를 활용하여 자동 증가를 달성합니다. 이는 "자동 증분 코드"의 중복을 피하기 위해 수행됩니다.
이 예제에서 자체 증분 코드는 매우 간단합니다. ++i 한 줄이면 됩니다. 이렇게 할 필요가 없습니다. 그러나 복잡한 자동 증가 논리가 있는 다른 예에서는 여전히 그렇게 해야 합니다.
효율성의 차이
증가 전 값을 반환할 필요가 없다면 pre-++와 post-++의 계산 효과는 동일합니다. 그러나 우리는 여전히 접두사 ++를 사용하는 것을 선호해야 합니다. 특히 사용자 정의 유형의 자동 증가 연산에 대해서는 더욱 그렇습니다.
Pre-++가 더 효율적입니다. 그 이유는 post-++가 임시 개체를 생성하기 때문입니다.
이는 Age의 post-post++ 코드 구현에서도 확인할 수 있습니다.
const Age operator++(int) //后置++
{
Age tmp = *this;
++(*this); //利用前置++
return tmp;
}
분명히 tmp는 임시 개체이므로 생성자와 소멸자의 추가 오버헤드가 발생합니다. 그러나 컴파일러는 경우에 따라 이러한 오버헤드를 최적화할 수 있습니다. 그러나 컴파일러의 동작에 의존하지 않는 것이 좋습니다.
따라서 빌트인 타입이 아닐때는 효율이 높기 때문에 pre-++를 사용해보세요.(post-increment, 저효율)
원본 링크: https://blog.csdn.net/randyjiawenjie/article/details/6747720