如果vector为空,std::vector::data()应该返回什么?

What should std::vector::data() return if the vector is empty?

本文关键字:vector 什么 返回 data 为空 std 如果      更新时间:2023-10-16

根据标准草案(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,您的有效范围仍然为空。

相关文章: