1. 程式人生 > >5.6~5.15 雙目運算子(指標運算)

5.6~5.15 雙目運算子(指標運算)

返回目錄

5.7 + -
對於涉及指標的算術運算,標準中有比較嚴格的限制條件:
參與運算的指標必須指向陣列物件中的元素,或者指向陣列物件最後一個元素的下一個元素(這是STL中能夠使用distance(v.begin(),v.end())計算元素個數的前提條件)。
(注:對於指向普通物件的指標,可以將該物件當成長度為1的陣列中的元素)(5.7-4)
否則,會導致未定義的行為。

指標加減一個整型型別,相當於對指標對應的陣列元素的下標進行加減操作。
如果陣列有N個元素,只要計算得到的下標在[0,N]之間,結果都是有效的,而且保證不會溢位,否則結果是未定義的。(5.7-5)

兩個指標相減,相當於對兩個指標對應的陣列元素的下標相減(5.7-6)
結果的型別是std::ptrdiff_t(在<cstddef>標頭檔案中)。ptrdiff_t具體是什麼型別是實現相關的,不過必然是有符號整型。
如果相減的結果溢位,那麼會導致未定義的行為。

對指標進行+0或者-0的操作不會對指標的值產生影響。(5.7-7)
如果兩個指標指向陣列物件中的同一個元素,或者都是NULL,那麼兩者相減將得到0

5.9~5.10 < > == !=
因為只有指向相同型別的指標才能夠進行比較,所以當指標參與比較運算的時候,會進行預設的指標型別轉換(0->(T *)0,T *->void *,Derived *->Base *,T *->T const *等等)(4.10&4.4),以使兩者的型別一致。

void
 *p;
const int *q;
int **pi;
const int *const *pci;
p <= q; // both converted to const void * before comparison
pi <= pci; // both converted to const int * const * before comparison

指標比較遵循以下的原則:

1、如果兩者都是NULL,則相等
2、如果僅其中之一是NULL,則不相等
3、如果兩個指標滿足前面指標的算術運算的要求,那麼比較的結果取決於它們指向元素的下標
4、如果兩個成員函式指標對應同一個物件的同一個函式(不能是虛擬函式),那麼兩者相等
(在下面的例子中,pdl指向的物件是L的基類B,pdr指向的物件是R的基類B,兩個物件並不不同,所以返回false:
struct
 B {
    int f();
};
struct L : B { };
struct R : B { };
struct D : L, R { };

void Test()
{
    int (B::*pb)() = &B::f;
    int (L::*pl)() = pb;
    int (R::*pr)() = pb;
    int (D::*pdl)() = pl;
    int (D::*pdr)() = pr;
    bool x = (pdl == pdr); // false
}

5、如果兩個指標指向同一個物件(非union)的非靜態成員變數,那麼它們的大小關係取決於它們宣告的順序
(注:必須是在同一個訪問許可權識別符號下,否則標準沒有規定返回值
(換句話說,對於在不同訪問許可權識別符號中定義的變數,具體的實現有權自由安排它們的順序。這點需要額外小心,特別是在建構函式的初始化列表中使用這些成員時)
在下例中,a必然在b的前面,而c和a、b的位置關係則取決於具體的實現:
public
 A
{
    int a;
    int b;
private:
    int c;
};

6、如果兩個指標指向同一個union中的成員變數,那麼兩者是相等的
7、對於其它情況,標準沒有規定比較的結果