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;
}
使用我的编译器输出:
0x0
0x7f896b403300
0x7f896b403300
0x0
这表明:
data()
确实可以是空指针,因此答案是(1)是(2)否(3)没有
但始终是零大小矢量的空指针
是的,显然我应该在问之前尝试过这个。
答案 0 :(得分:21)
“有效范围”由[iterator.requirements.general] / 7(C ++ 14)定义:
“范围
[i,j)
有效且当且仅当j
可以i
”时才有效。
幸运的是,C ++定义了将0
添加到空指针会产生空指针。那么,空指针是一个空指针可达吗?这由同一部分的第6点定义:
迭代器
j
从迭代器i
被称为可到达当且仅当表达式++i
的应用程序的有限序列{ {1}}。
零长度序列是有限序列,因此i == j
可能返回空指针。
因此,您的问题的答案是:
- 醇>
data()
可以是空指针吗?
是强>
- 可以安全地解除引用吗? (即使它指向垃圾。)
醇>
否强>
- 两个不同(零长度)矢量之间是否保证不同?
醇>
否强>
答案 1 :(得分:6)
评论太长,所以发布在这里。
我期望迭代器对于空序列是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;
}
这确实打印
0, 0
0, 0
现在对于一个空容器,有效范围的唯一合理操作是begin() == end()
。不,垃圾无法解除引用,所以* v.begin()不是问题。
答案 2 :(得分:5)
来自标准:
23.3.6.4 [vector.data]
T * data()noexcept;
const T * data()const noexcept;
返回:指针,使 [data(),data()+ size())为有效范围。为一个 非空向量,data()==&amp; front()。
因此对于空向量允许为空,但不一定是可解除引用也不是唯一的。