2010-03-08 7 views
5

Aşağıdaki kodu göz önünde bulundurun:Teller; &s+1; Yasal? 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; 
} 

Burada ilgi &myAry[numStrs]: numStrs 5'e eşittir, yani &myAry[numStrs] var olmayan bir şeye işaret eder; dizideki altıncı öğesi. Yukarıdaki kodda bunun bir başka örneği daha vardır: myVec.end(), vektör myVec'un bir ucunu işaret eder. Var olmayan bu elementin adresini almak için mükemmel bir yasallık var. Xzx60'ın boyutunu biliyoruz, bu yüzden string s'nin bir C stili dizisinin 6. elemanının adresini işaret etmesi gerektiğini biliyoruz. Sadece bu işaretçiyi değerlendirdiğimiz ve asla dere atmadığımız sürece iyiyiz. Eşitlik için diğer işaretçilerle bile karşılaştırabiliriz. STL bunu her zaman bir dizi yineleyici üzerinde hareket eden algoritmalarda yapar. Xzx62 yineleyici, son noktayı işaret eder ve döngüler, bir != end() sayacında dönmeye devam eder.

Şimdi şunu düşünün:

#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; 
} 

Bu kod yasal ve iyi tanımlanmış mı? Xzx64'te olduğu gibi, &myAry[numStrs]'te olduğu gibi, bir dizi öğesinin adresini &myAry[numStrs]'te olduğu gibi yasal ve iyi tanımlanmış olması, yasal ve iyi tanımlanmış olmalıdır?

cevap

12

O uzunluğu 1 bir dizi sanki bir dizinin, ve tek bir nesne "ucunun ötesindeki bir" tedavi edilebilir bir işaretçi için yasal olup UB olduğu; bununla birlikte, &ptr[1] dereferansın teknikliği ve ardından adresi almak için ptr + 1'u kullanmanız gerekir. Bu, 'un array + size haline gelmesi için de geçerlidir.

Eğer ben farkındayım hangi tüm platformlarda beklediğiniz gibi çalışacaktır var, ama açık bir şekilde doğru formu kullanmanın ne kadar kolay verilen Ne yani, bunu yerine yapmak değil hiçbir sebep göremiyorum.

+8

+ 1. Bunu yapmanın kolay bir yolu değil, aynı zamanda operatörün aşırı yüklenmesiyle (daha fazla yüklenmek kötü, evet. Ama bu sadece bağımlılıkların nasıl sürüklendiğini gösteriyor) daha fazla tuzaktan kaçınmaktır. Tanımlanmamış davranışlardan uzak kalmak en iyisidir. –

5

5,6/4 "Katkı operatörler" olarak C++ standart söyler: Bu operatörlerin amacıyla

, nonarray nesneye bir işaretçi, bir dizi ilk elemanı için bir işaretçi olarak aynı şekilde davranır öğe türü olarak nesnenin türü ile bir uzunluk.

C99 standart 6.5.6/7 temelde aynı söylüyor. Doğruluğundan