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',我还有数据指针,所以我可以将它用作常规数组。
// ...
}//这里结束了我的作用域,所以向量被销毁,内存被释放。
问题是“这样我就可以将其用作数组”是否是一个安全的假设
不管争论如何,我只是对上述问题感到好奇。无论如何,关于论点:
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]};