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

时间:2014-08-21 06:45:23

标签: c++ vector

根据标准草案(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?例如,一个实现可以执行默认大小的初始分配并返回一个(非空)指针吗?

编辑:有几个答案侧重于空范围的有效性。我完全同意。

我真的希望看到一个很好的参考或解释:是允许必须返回null或可能返回非null?

4 个答案:

答案 0 :(得分:12)

范围的约定是[inclusive, exclusive),即如果迭代范围[X,Y),您将在概念上执行以下操作(伪代码):

for( iterator ii = X; ii != Y; ++ii) {
...
}

这允许将空范围表示为[X,X)。此<#>完整定义每个地址,无论它是有效还是无效。

那说data()的要求是(强调我的)

  

23.3.6.4 [vector.data]

     

T * data()noexcept;

     

const T * data()const noexcept;

     

返回:指针,使 [data(),data()+ size())为有效范围。为一个   非空向量,data()==&amp; front()。

在我看来,唯一的无条件保证是[data(),data() + size())应该是有效范围。对于size() == 0,成员函数data()可以返回任何值,范围将是有效的空范围。因此,我会说如果size()为零,则允许实现返回非空指针。

答案 1 :(得分:4)

如果向量为空(),标准中的任何措辞都没有建议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

答案 2 :(得分:0)

有一种状态是对象可以有效但未指定:

  

有效但未指定的状态 [§17.3]

     

除了对象之外没有指定的对象状态   满足不变量,对象上的操作按指定行为   对于它的类型

     

[示例:如果std :: vector类型的对象x有效,但是   未指定的状态,可以无条件地调用x.empty()   仅当x.empty()返回false时才能调用x.front()。 -end example ]

读取C ++标准时,向量为空时未指定data()的状态。因此,状态是有效但未指定的状态。因此,当向量为空时,data()的返回值可以是任何值(null或随机值)。这取决于编译器的实现。

在这种情况下,按照§17.3中的示例,您应该在使用empty()之前调用data(),以确保返回的值符合您的预期。

if (!v.empty())
   do_something(v.data())

答案 3 :(得分:0)

是的,这是可能的,而libstdc ++正在这样做。 您可以查看data() in libstdc++

的文档
 data() _GLIBCXX_NOEXCEPT
 { return _M_data_ptr(this->_M_impl._M_start); }

但是,可能无法指定对此指针执行操作,因为您在不知情的情况下访问向量中的非初始化范围(例如,您不知道内存束的确切大小)。此外,当size()为0时,您的有效范围仍为空。