考虑下面的代码:

#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的一过去的最末端。这是perfecly法律借此元素一个不存在的地址。我们知道string的大小,所以我们知道strings的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也是一个数组?

有帮助吗?

解决方案

它是合法的并且不UB有对“一个过去的结束”的阵列,以及任何单个对象可以如同它是在长度为1的阵列来处理的指针;但是,你需要使用ptr + 1,而不是由于&ptr[1]提领,然后取地址的技术性。这也适用于&array[size]成为array + size

你有什么,你期望在其中我知道所有平台上都可以工作,但考虑到它是多么容易使用明确正确的形式,我看不出有什么理由不这样做吧。

其他提示

在5.6 / 4 “加法运算符” C ++标准表示:

  

有关这些操作符的目的,一个指向非数组对象的行为相同的指针长度的一个阵列与对象作为其元素类型的类型的第一元件。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top