pre-++와 post-++ 연산자 오버로딩의 차이점(상세)

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

추천

출처blog.csdn.net/SFDWU3QVG/article/details/125715842