如果vector为空,std::vector::data()应该返回什么?
What should std::vector::data() return if the vector is empty?
根据标准草案(23.3.6.4 vector data), data()指向底层数组,[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 (GCC 4.2.1和Intel 12.1)上,我得到一个非空地址。
是允许vector::data()
还是应该返回null?例如,实现可以执行默认大小的初始分配并返回指向它的(非空)指针吗?
Edit:几个答案关注空范围的有效性。我完全同意这一点。
我真的很想看到一个很好的参考或解释:它是允许, 必须返回null或可能它也返回非空?
范围的约定是[inclusive, exclusive)
,也就是说,如果您在范围[X,Y)
上迭代,您将在概念上执行以下操作(伪代码):
for( iterator ii = X; ii != Y; ++ii) {
...
}
允许将空范围表示为[X,X)
。此外,这个空范围为每个地址定义得很好,无论它是有效的还是无效的。
也就是说,data()
的要求是(强调我的):
23.3.6.4 [vector.data]
T* data() noexcept;
const data() const noexcept;
返回:使得[data(),data() + size())是有效范围的指针。对于一个非空向量,data() == &front().
在我看来,唯一的无条件保证是[data(),data() + size())
应该是一个有效范围。对于size() == 0
,成员函数data()
可以返回任何值,范围将是一个有效的空范围。因此,如果size()
为零,
如果向量为空(),则标准中的任何措辞都不建议为data()给定值。
这里有一些明确的证据来证明为什么你不应该假设它可能是零,即使它有时是零:
#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 存在一种状态,即对象可以有效但未指定:
有效但未指定状态[§17.3]
一个对象的状态,除了对象的状态之外没有指定满足不变量,并且对象上的操作按照指定的方式执行对于其类型
[示例:如果std::vector类型的对象x在有效的但是未指定状态,x.empty()可以无条件调用,并且只有在x.empty()返回false时才能调用X.front()。端例子)
读c++标准,当vector为空时,不指定data()
的状态。因此,状态有效,但未指定状态。因此,当向量为空时,data()
的返回值可以是任何值(null或随机值)。这取决于编译器的实现。
在这种情况下,按照§17.3的例子,你应该在使用data()
之前调用empty()
,以确保返回的值是你期望的。
if (!v.empty())
do_something(v.data())
是的,这是可能的,libstdc++正在这样做。您可以查看libstdc++
中data()的文档。 data() _GLIBCXX_NOEXCEPT
{ return _M_data_ptr(this->_M_impl._M_start); }
然而,在这个指针上执行操作可能没有被指定,因为你正在访问一个未初始化的向量范围,而不知道它的知识(例如,你不知道内存束的确切大小)。此外,由于size()
为0,您的有效范围仍然为空。
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 在自定义 std::vector-like 容器中处理指针和非指针模板类型的最佳方法是什么?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 向后迭代 std::array 或 std::vector 的正确方法是什么?
- 这句话是什么意思 - " vector<long long> distance(n, std::numeric_limits<long long>::max()); "?
- 最接近"std::atomic<std::vector>"是什么?
- 行 - " vector<int> used(adj.size(), 0); "是什么意思?
- 将vector<vector<double>>从x86平台中创建的一个进程发送到x64中构建的另一个进程的最快方法是什么
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 代码中的"vector<<int>vector>&index"是什么意思?
- 释放 std::vector 中指针内存的最有效方法是什么?
- 当我们push_back元素时,std::vector 什么时候会放大自己?
- 如果我将"reference to vector"分配给"vector"会发生什么情况
- vector.back()和vector.end()有什么区别
- 这个(const vector<vector<int> > &A)"代码段是什么意思?
- 什么是vector<int,int>它甚至有效吗?
- std::shared_ptr<std::vector有什么问题<double>>
- 带有 std::vector 和 std::queue 的 Prim's 算法,我的代码有什么问题?
- std::vector<int> 和 std::vector* 有什么区别<int>?