cppreference有这样的说明std::vector::data
:
返回指向用作元素存储的基础数组的指针.指针使得范围
[data(); data() + size())
始终是有效范围,即使容器为空.
"有效范围"到底意味着什么?data()
如果向量是零长度会返回什么?
具体来说,对于零长度矢量:
data()
成为空指针吗?我正在使用一个带有数组的C库,即使对于零长度数组也不允许空指针.但是,如果数组长度为零,它实际上不会取消引用数组存储指针,它只检查它是否为NULL
.我想确保我可以安全地传递data()
给这个C库,所以唯一相关的问题是上面的(1).(2)和(3)只是出于好奇而出现类似情况.
更新
根据未转化为答案的评论,我们可以尝试以下程序:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
cout << v.data() << endl;
v.push_back(1);
cout << v.data() << endl;
v.pop_back();
cout << v.data() << endl;
v.shrink_to_fit();
cout << v.data() << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用我的编译器输出:
0x0
0x7f896b403300
0x7f896b403300
0x0
Run Code Online (Sandbox Code Playgroud)
这表明:
data()
确实可以是空指针,因此答案是(1)是(2)否(3)否
但它并不总是零大小向量的空指针
是的,显然我应该在问之前尝试过这个.
M.M*_*M.M 21
"有效范围"由[iterator.requirements.general]/7(C++ 14)定义:
"
[i,j)
当且仅当j
可以从i
" 到达时,范围才有效.
幸运的是,C++定义了添加0
空指针会产生空指针.那么,是否可以从空指针到达空指针?这由同一部分的第6点定义:
迭代器
j
被称为到达从一个迭代i
,当且仅当存在的表达的应用程序的有限序列++i
,使i == j
.
零长度序列是有限序列,因此data()
可以返回空指针.
因此,您的问题的答案是:
- 可以
data()
成为空指针吗?
是
- 可以安全地解除引用吗?(即使它指向垃圾.)
没有
- 是否保证两个不同(零长度)矢量之间的差异?
没有
评论太长,所以发帖在这里.
我期望迭代器对于空序列是nullptr所以我测试了它.
#include <iostream>
#include <vector>
void pr(std::vector<int>& v){
std::cout << &*v.begin() << ", " << &*v.end() << "\n";
}
// technically UB, but for this experiment I don't feel too bad about it.
// Thanks @Revolver
int main(int argc, char** argv) {
std::vector<int> v1;
std::vector<int> v2;
pr(v1);
pr(v2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这确实打印出来了
0, 0
0, 0
Run Code Online (Sandbox Code Playgroud)
现在对于一个空容器,有效范围的唯一合理操作是begin() == end()
.不,垃圾不能被解除引用所以*v.begin()不是一个问题.
从标准:
23.3.6.4 [vector.data]
T*data()noexcept;
const T*data()const noexcept;
返回:指针使得[data(),data()+ size())是有效范围.对于非空向量,data()==&front().
因此,对于空向量,它允许为null,但不一定是dereferencable也不是唯一的.