C++ reserve()-data()对空向量的技巧-正确吗?

C++ reserve()-data()对空向量的技巧-正确吗?,c++,c++11,stl,C++,C++11,Stl,正如我们所知,当像std::vector vect(n)或empty\u vect.resize(n)这样初始化时,std::vector不仅分配所需的内存量,而且还使用默认值对其进行初始化(即调用默认构造函数)。这会导致不必要的初始化,特别是如果我有一个整数数组,并且我想用一些特定的值填充它,而这些值不能通过任何向量构造函数提供 另一方面,容量在调用中分配内存,如empty\u vect.reserve(n),但在这种情况下,vector仍然是空的。因此size()返回0,empty()返回t

正如我们所知,当像
std::vector vect(n)
empty\u vect.resize(n)
这样初始化时,std::vector不仅分配所需的内存量,而且还使用默认值对其进行初始化(即调用默认构造函数)。这会导致不必要的初始化,特别是如果我有一个整数数组,并且我想用一些特定的值填充它,而这些值不能通过任何向量构造函数提供

另一方面,容量在调用中分配内存,如
empty\u vect.reserve(n)
,但在这种情况下,vector仍然是空的。因此
size()
返回
0
empty()
返回
true
运算符[]
生成异常

现在,请查看代码:

{ // My scope starts here...

    std::vector<int> vect;
    vect.reserve(n);
    int *data = vect.data();

    // Here I know the size 'n' and I also have data pointer so I can use it as a regular array.
    // ...

} // Here ends my scope, so vector is destroyed, memory is released.
{//我的范围从这里开始。。。
std::vector-vect;
矢量储备(n);
int*data=vect.data();
//这里我知道大小'n',我还有数据指针,所以我可以将它用作常规数组。
// ...
}//这里结束了我的作用域,所以向量被销毁,内存被释放。
问题是“这样我就可以将其用作数组”是否是一个安全的假设

不管争论如何,我只是对上述问题感到好奇。无论如何,关于论点:

  • 它分配内存,并在函数返回时自动释放内存
  • 代码不会执行不必要的数据初始化(在某些情况下可能会影响性能)
  • 不,你不能用它

    标准(当前草案,C++11中的等效措辞):

    constexpr T*data()无异常

    constexpr const T*data()const noexcept

    返回:
    [data(),data()+size())
    为有效范围的指针。 对于非空向量,
    data()==addressof(front())

    您无法保证可以通过超出向量大小的指针进行访问。特别是对于空向量,最后一句话不适用,因此您甚至无法确保获得指向基础数组的有效指针

    目前无法将
    std::vector
    与默认初始化元素一起使用


    如评论中所述,您可以改用
    std::unique_ptr
    (需要
    #include
    ):

    auto data=std::unique_ptr{new int[n]};
    
    它将为您提供一个指向动态大小的
    int
    数组的
    std::unique_ptr
    智能指针,该数组将在
    数据的生存期结束时自动销毁,并可通过移动操作转移其所有权

    它可以使用常用的指针语法直接取消引用和索引,但不允许使用直接指针算法。可以通过
    data.get()
    从中获取原始指针

    但是,它不提供
    std::vector
    接口。特别是,它不提供对其分配大小的访问,并且无法复制



    注意:我在这个答案的前一个版本中犯了一个错误。我使用了
    std::make_unique
    ,但没有意识到它实际上也执行了值初始化(对于
    int
    s初始化为零)。在C++20中,将有
    std::make_unique\u default_init
    默认初始化(因此,将
    int
    s保留为不确定值)。

    因此,您希望像
    unique\u ptr
    一样使用它。如果不需要向量API,则使用
    unique\u ptr
    data()中没有对象
    ,您不能像那样使用该指针。无需使用
    调整大小
    ,有
    插入
    推回
    等。如果OP在保留后做了推回(0),则data()将返回有效指针。这是否使他的假设安全(r)?@engf-010是的,指针是有效的,但它对OP想要做的事情没有真正的帮助。引用的子句只说明
    [data(),data()+size())
    是一个有效的范围。因此,您最多可以将
    size()
    添加到
    data()
    (这会给你一个超出范围的指针,这个范围可能不会被取消引用)。即使超出范围的指针算术也不能保证是有效的。从你的回答中,我认为你(还有我)尽管您的形式正确,但我们对此并不完全确信。但阅读vector中的所有重新分配子句后,我只能得出结论,范围限制过于严格。@如果超出指向对象所属的数组,则engf-010指针算法通常具有未定义的行为。
    std::vector
    guArante告诉您,初始化的元素形成一个数组,指针算法在该数组上工作,但是在
    [data(),data()+size)
    范围之外没有构造的
    int
    对象,因此超出我提到的指针算法将具有未定义的行为。
    auto data = std::unique_ptr<int[]>{new int[n]};