Increment & Decrement Operator (++ & --)
증가/감소 연산자 (++ & --)
- 말 그대로, 변수의 값을 1만큼 더하거나 빼는 연산자이다.
- 변수의 앞 혹은 뒤에 붙이는 방식에 따라 Prefix(접두어)방식, Postfix(접미어)방식으로 나뉜다.
- 접두어, 접미어 방식은 결과적인 측면에서 피연산자에 가져오는 효과(증가/감소)는 동일하지만 증감 연산을 적용하는 시점이 다르다.
Prefix Version (접두어 방식)
int num = 10;
++num; // Prefix Ver.
--num; // Prefix Ver.
- 접두어 방식의 증감연산은 변수의 값을 먼저 증가시킨 후, 증가된 값으로 표현식의 값에 반영되는 방식이다.
Postfix Version (접미어 방식)
int num = 10;
num++; // Postfix Ver.
num--; // Postfix Ver.
- 접미어 방식의 증감연산은 변수가 현재 가지고 있는 값으로 표현식의 값을 평가한 후에 증감연산을 적용하는 방식이다.
연산결과 비교
int a = 5;
int b = ++a;
// 변수 b에는 6이 저장된다.
int x = 7;
int y = x--;
// 변수 y에는 7이 저장되며, 이 표현식이 끝나면 x의 값은 6이된다.
* 모호한 상황을 방지하기 위해 한 구문에서 같은 값을 여러 번 증감시키는 것은 피해야 한다.
x = 2 * x++ * (3 - ++x);
// 시스템에 따라, 결과가 다를 수 있다.
- C++에서는 이러한 종류의 구문이 정확하게 동작하는 것을 보장하지 않는다.
- 또한, C++에서는 부분 수식이 각각 평가된 후에 x를 증가시키는지, 또는 모든 수식의 평가를 끝낸 후에 x를 증가시키는지를 구체적으로 규정해놓지 않았다.
Prefix Version과 Postfix Version의 구현상의 차이
- C++에서는 접두어 방식과 접미어 방식의 증감 연산자에 대한 오버로딩을 허용하므로, 프로그래머는 자신만의 클래스를 위한 증감연산자를 정의할 수 있다.
- 여기서, 접두어 방식의 연산자는 값을 증가시키고 증가된 값을 리턴하는 방식으로 함수를 정의하며, 접미어 방식은 먼저 값의 복사본을 만든 다음, 복사본의 값을 증가시키고 그 복사본을 리턴하는 방식으로 함수를 정의하게 된다.
- 설계상의 이유로, 사용자 지정 데이터형에 대한 접두어/접미어 방식 증감연산자 사용시에는 접두어 버전이 접미어 버전보다 약간 더 효율적이다.
(논리적으로 접두어/접미어 방식 중 어느것을 택해도 상관없을 경우엔 접두어 버전을 선택하자!)
- Built-in 데이터형에 대해서는 어느 방식을 사용해도 거의 차이가 없다.
포인터에 대한 증감연산
- 증감연산자는 기본 변수뿐만 아니라, 포인터에도 사용할 수 있다.
- 포인터가 지시하는 데이터형의 바이트 수만큼 그 값을 증감시킨다.
double arr[5] = {1.2, 3.4, 5.6, 7.8, 9.0};
double* pt = arr;
++pt; // pt는 arr[1]을 가리키게 된다.
(double형이 8Byte를 차지하는 시스템에서, 8만큼 값이 증가함)
- * 연산자와 증감연산자를 통해서 지시하는 값에 대한 증감연산을 수행할 수도 있는데, 이 경우에는 연산자 우선순위가 중요하며, 소괄호를 적절하게 사용해야 한다.
* 연산자 우선순위
Postfix Op > Prefix Op = Indirect Value Op
- 접두형 연산자와 간접값 연산자는 우선순위가 같으며, 오른쪽에서 왼쪽으로 결합된다.
- 접미형 연산자는 왼쪽에서 오른쪽으로 결합된다.
*++pt; // 접두형 증가연산 -> 간접값 연산 (주솟값 증가 후, 간접값 연산)
++*pt; // 간접값 연산 -> 접두형 증가연산 (지시하는 값 증가)
(*pt)++; // 간접값 연산(소괄호 우선) -> 접미형 증가연산 (지시하는 값 증가)
*pt++; // 접미형 증가연산 -> 간접값 연산 (주솟값 증가 후, 간접값 연산)