如果vec.size()== 0,vec.data()会返回什么?

时间:2016-03-15 09:20:04

标签: c++ vector

cppreferencestd::vector::data的注释:

  

返回指向用作元素存储的基础数组的指针。指针是这样的,即使容器为空,范围[data(); data() + size()) 始终是有效范围。

“有效范围”到底意味着什么?如果向量为零长度,data()会返回什么?

具体来说,对于零长度矢量:

  1. data()可以是空指针吗?
  2. 可以安全地解除引用吗? (即使它指向垃圾。)
  3. 两个不同(零长度)矢量之间是否保证不同?
  4. 我正在使用一个带有数组的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)没有

    • 始终是零大小矢量的空指针

    是的,显然我应该在问之前尝试过这个。

3 个答案:

答案 0 :(得分:21)

“有效范围”由[iterator.requirements.general] / 7(C ++ 14)定义:

  

“范围[i,j)有效且当且仅当j可以i”时才有效。

幸运的是,C ++定义了将0添加到空指针会产生空指针。那么,空指针是一个空指针可达吗?这由同一部分的第6点定义:

  

迭代器j从迭代器i被称为可到达当且仅当表达式++i的应用程序的有限序列{ {1}}。

零长度序列是有限序列,因此i == j可能返回空指针。

因此,您的问题的答案是:

  
      
  1. data()可以是空指针吗?
  2.   

  
      
  1. 可以安全地解除引用吗? (即使它指向垃圾。)
  2.   

  
      
  1. 两个不同(零长度)矢量之间是否保证不同?
  2.   

答案 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()。

因此对于空向量允许为空,但不一定是可解除引用也不是唯一的。