字符串s; &安培; S + 1;法律? UB?

时间:2010-03-08 23:18:46

标签: c++ undefined-behavior

请考虑以下代码:

#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()迭代器指向结束,并且循环在计数器!= 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也是数组,它是否合法且定义明确? / p>

2 个答案:

答案 0 :(得分:12)

指向数组的“一个接一个”的指针是合法的而不是UB,任何单个对象都可以被视为长度为1的数组;但是,由于ptr + 1解除引用的技术性,然后获取地址,您需要使用&ptr[1]。这也适用于&array[size]成为array + size

你所拥有的将在我所知道的所有平台上按预期工作,但考虑到使用明确正确的形式是多么容易,我认为没有理由不这样做。

答案 1 :(得分:5)

5.6 / 4“添加剂运算符”中的C ++标准说:

  

出于这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。

C99标准6.5.6 / 7基本相同。