5

考虑以下代码:

#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,因此我们知道 s 的 C 样式数组的第 6 个元素的地址string必须指向的位置。只要我们只评估这个指针并且从不取消引用它,我们就可以了。我们甚至可以将它与其他指针进行比较以判断是否相等。STL 一直在作用于一系列迭代器的算法中这样做。迭代器end()指向末尾,并且循环在 counter 时继续循环!= 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也是一个数组是否应该是合法且定义明确的?

4

2 回答 2

12

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

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

于 2010-03-08T23:27:26.927 回答
5

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

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

C99 标准 6.5.6/7 说的基本相同。

于 2010-03-08T23:31:15.327 回答