请考虑以下代码:
#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>
答案 0 :(得分:12)
指向数组的“一个接一个”的指针是合法的而不是UB,任何单个对象都可以被视为长度为1的数组;但是,由于ptr + 1
解除引用的技术性,然后获取地址,您需要使用&ptr[1]
。这也适用于&array[size]
成为array + size
。
你所拥有的将在我所知道的所有平台上按预期工作,但考虑到使用明确正确的形式是多么容易,我认为没有理由不这样做。
答案 1 :(得分:5)
5.6 / 4“添加剂运算符”中的C ++标准说:
出于这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。
C99标准6.5.6 / 7基本相同。