2010-03-08 85 views
5

考慮下面的代碼:string s; &s+1;法律? UB?

#include <cstdlib> 
#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
using namespace std; 

int main() 
{ 
    string myAry[] = 
    { 
     "Mary", 
     "had", 
     "a", 
     "Little", 
     "Lamb" 
    }; 
    const size_t numStrs = sizeof(myStr)/sizeof(myAry[0]); 

    vector<string> myVec(&myAry[0], &myAry[numStrs]); 

    copy(myVec.begin(), myVec.end(), ostream_iterator<string>(cout, " ")); 

    return 0; 
} 

這裏感興趣的是&myAry[numStrs]:numStrs等於5,所以&myAry[numStrs]點的東西,不存在;數組中的第六個元素。在上面的代碼中有另一個例子:myVec.end(),它指向矢量myVec的一個尾部。採用這個不存在的元素的地址是完全合法的。我們知道string的大小,所以我們知道string的C形陣列的第6個元素的地址必須指向哪個地址。只要我們只評估這個指針並且永不解引用它,我們就可以。我們甚至可以將它與其他指針進行比較以求平等。 STL一直在執行一系列迭代器的算法。迭代器指向末尾,並且循環保持循環,而計數器則爲!= end()

所以現在考慮這個問題:

#include <cstdlib> 
#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
using namespace std; 

int main() 
{ 
    string myStr = "Mary"; 
    string* myPtr = &myStr; 
    vector<string> myVec2(myPtr, &myPtr[1]); 

    copy(myVec2.begin(), myVec2.end(), ostream_iterator<string>(cout, " ")); 

    return 0; 
} 

這段代碼的法律和明確定義的?像&myAry[numStrs]那樣採用數組元素的地址是合法的和明確的,因此它應該是合法的並且明確地假定myPtr也是一個數組?

回答

12

它是合法的並且不UB有對「一個過去的結束」的陣列,以及任何單個對象可以如同它是在長度爲1的陣列來處理的指針;但是,您需要使用ptr + 1,而不是由於&ptr[1]取消引用的技術性,然後獲取地址。這也適用於&array[size]變爲array + size

你有什麼,你期望在其中我知道所有平臺上都可以工作,但考慮到它是多麼容易使用明確正確的形式,我看不出有什麼理由不這樣做,而不是。

+8

+1技術準確性。不僅很容易把事情做對,但它也避免了運營商'&'過載(這是不好過載,是的。但是,這顯示瞭如何一個剛剛拖動依賴關係)進一步陷阱。最好不要留下未定義的行爲。 – 2010-03-09 00:07:38

5

的C++ 5.6/4「加法運算符」的標準說:

對於這些操作符的目的,一個指向非數組對象的行爲相同的指針數組的第一元素長度與對象的類型作爲其元素類型。

C99標準6.5.6/7基本上說是相同的。

相關問題