根据标准草案( 23.3.6.4矢量数据 ),数据()点为基础数组和[data(), data() + size())
必须是有效的范围:
T* data() noexcept;
const T* data() const noexcept;
1 Returns: A pointer such that [data(),data() + size()) is a valid range. For a non-empty vector,
data() == &front().
2 Complexity: Constant time
但是,如果载体是什么空? 当我构造大小为零的矢量:
#include <vector>
#include <iostream>
int main() {
const int NUM = 0*10;
std::vector< double > v( NUM, 0.0 );
std::cerr << "V : "<< v.data() << std::endl;
}
MSVC 2010返回NULL,但在Linux上(与海湾合作委员会4.2.1和英特尔12.1)我得到一个非空的地址。
是vector::data()
允许,还是应该返回null? 能否实现,例如,做一个默认大小的初始分配和(非空)指针返回到它?
编辑:有几个答案集中在一个空范围的有效性。 我完全同意。
我真的想看到一个很好的参考或解释:是否允许 , 必须将它返回null 或者它也返回非空?
对于范围的约定是[inclusive, exclusive)
,也就是说,如果我们通过遍历范围[X,Y)
你会做概念以下(伪代码):
for( iterator ii = X; ii != Y; ++ii) {
...
}
这允许以表达一个空范围为[X,X)
另外这个空范围非常清楚每个地址定义,不管它是有效还是无效。
这表示,对于要求data()
是(重点煤矿):
23.3.6.4 [vector.data]
T *数据()noexcept;
常量T *数据()const的noexcept;
返回:指针,使得[数据(),数据()+大小())是一个有效的范围内 。 对于非空载体,数据()==&前()。
在我看来,唯一的无条件的保证是, [data(),data() + size())
应该是一个有效的范围。 对于size() == 0
成员函数data()
可以返回任何值和范围将是一个有效的空范围。 因此,我要说的是, 实现被允许返回一个非空指针size()
是零 。
在标准的措辞没有一个建议数据)给定的值(如果该载体是空的()。
这里就是为什么你不应该假设它可能是零,尽管它有时是一些明确的证据:
#include <vector>
#include <iostream>
void value_of_data(std::vector<int> const& v)
{
std::cout << "empty() = " << v.empty() << ", " << "data() = " << static_cast<const void*>(v.data()) << std::endl;
}
int main()
{
std::vector<int> v;
value_of_data(v);
v.resize(100, 0);
v.clear();
value_of_data(v);
}
示例输出(gcc7.2,-O2,LINUX):
empty() = 1, data() = 0
empty() = 1, data() = 0x7ebc30
http://coliru.stacked-crooked.com/a/dd1d13200c8b9a3a
是的,这是可能的,和libstdc ++是这样做的。 你可以看看的文档中的libstdc数据()++
data() _GLIBCXX_NOEXCEPT
{ return _M_data_ptr(this->_M_impl._M_start); }
然而,在这个指针执行操作可能不被指定,如您正在访问您的载体内的未初始化的范围,没有它的知识(例如,你不知道内存一堆的确切大小)。 此外,如size()
为0时,您的有效范围仍然是空的。
有一个对象可以是有效的,但不确定的状态:
有效的,但不确定状态 [§17.3]
并非只是对象的不变量的对象遇到的行为和操作规定被作为其类型指定的对象状态
[ 实施例:如果类型为std ::矢量的一个对象x处于有效但非指定状态,x.empty()可以无条件地调用,并且x.front()可以被称为仅当x.empty()返回false。 末端示例 ]
读C ++标准,的状态data()
时,向量是空没有被指定。 所以,国家是有效的,但不确定状态 。 因此,返回的值data()
时,向量是空的可以是任何东西(null或随机值)。 这取决于执行的编译器。
在这种情况下,按照§17.3的例子,你应该调用empty()
使用前data()
以确保返回的值是为您的期望。
if (!v.empty())
do_something(v.data())