複合賦值操作符有 +=, -=, *=, /=,%=, <<=, >>=, &=, ^=, |=。
下面以+=為例
a += expression (1)
等價於:
a = a + expression (2)
但是,這裡是有區別的,(1)式中的a(如數組下標訪問的元素)只求值一次,(2)式中的a求值兩次,當然編譯器也許會最佳化,可能會使得(2)式效果和(1)式一樣,但是有例外的情況,編譯器是無法最佳化的。如:
int f(int x){return x;} int a[10] = {0};int x = 2; a[f(x) + 1] += 1; // (1)a[f(x) + 1] = a[f(x) +1] +1; // (2)
以上兩個運算式機器代碼是完全不同的,對於(2)式,由於是調用函數,編譯器並不能確定每次函數都返回相同的值(即是否有副作用),所以編譯器對此無能為力,不能對此最佳化,因此也就會去乖乖地調用兩次函數,而(1)式只調用一次函數,參見VS2010下的彙編代碼:
a[f(x) + 1] = a[f(x) +1] +2;013B1413 mov eax,dword ptr [ebp-3Ch] 013B1416 push eax 013B1417 call @ILT+110(_f) (13B1073h) 013B141C add esp,4 013B141F mov esi,dword ptr [ebp+eax*4-2Ch] 013B1423 add esi,2 013B1426 mov ecx,dword ptr [ebp-3Ch] 013B1429 push ecx 013B142A call @ILT+110(_f) (13B1073h) 013B142F add esp,4 013B1432 mov dword ptr [ebp+eax*4-2Ch],esi a[f(x) + 1] += 2;013B1436 mov eax,dword ptr [ebp-3Ch] 013B1439 push eax 013B143A call @ILT+110(_f) (13B1073h) 013B143F add esp,4 013B1442 lea ecx,[ebp+eax*4-2Ch] 013B1446 mov dword ptr [ebp-104h],ecx 013B144C mov edx,dword ptr [ebp-104h] 013B1452 mov eax,dword ptr [edx] 013B1454 add eax,2 013B1457 mov ecx,dword ptr [ebp-104h] 013B145D mov dword ptr [ecx],eax
因此,如果我們能確定運算式中不含有副作用的元素(如上面的函數f),那麼我們應盡量使用複合賦值操作符,不失效率同時書寫方便。