c++ - 保留() - 空向量上的数据()技巧 - 正确吗?
问题描述
众所周知,std::vector 在初始化时std::vector vect(n)
不仅empty_vect.resize(n)
会分配所需的内存量,还会使用默认值初始化它(即调用默认构造函数)。这会导致不必要的初始化,特别是如果我有一个整数数组并且我想用一些无法通过任何向量构造函数提供的特定值填充它。
另一方面,容量在调用中分配内存empty_vect.reserve(n)
,但在这种情况下,向量仍然是空的。所以size()
返回0
,empty()
返回true
,operator[]
产生异常。
现在,请查看代码:
{ // 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.
问题是“所以我可以将它用作数组”是否是一个安全的假设?
不管争论,我只是对上述问题感到好奇。无论如何,至于论点:
- 它分配内存并在函数返回时自动释放它
- 代码不执行不必要的数据初始化(在某些情况下可能会影响性能)
解决方案
不,你不能使用它。
标准(当前草案,C++11 中的等效措辞)在 [vector.data] 中说:
constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
返回:
[data(), data() + size())
一个有效范围的指针。对于非空向量,data() == addressof(front())
。
您无法保证可以通过超出向量大小的指针进行访问。特别是,对于一个空向量,最后一句话不适用,因此您甚至无法确定您是否获得了指向底层数组的有效指针。
当前无法使用std::vector
默认初始化的元素。
如评论中所述,您可以std::unique_ptr
改用(需要#inclue<memory>
):
auto data = std::unique_ptr<int[]>{new int[n]};
这将为您提供一个std::unique_ptr<int[]>
指向动态大小的数组的智能指针,该数组int
将在生命周期结束时自动销毁,data
并且可以通过移动操作转移其所有权。
它可以使用通常的指针语法直接取消引用和索引,但不允许直接指针算术。可以通过 从中获取原始指针data.get()
。
但是,它没有为您提供std::vector
界面。特别是它不提供对其分配大小的访问,并且不能被复制。
注意:我在此答案的先前版本中犯了一个错误。我使用std::make_unique<int[]>
时没有意识到它实际上也执行值初始化(对于int
s 初始化为零)。在 C++20 中std::make_unique_default_init<int[]>
,将默认初始化(因此使int
s 具有不确定的值)。
推荐阅读
- xml - 你如何在 xsl 中编写特殊字符?
- excel - 如何从 Excel 表格中的非唯一值返回行和列标签?
- arrays - 使用数组和指针的龟兔赛跑
- javascript - 我如何在按钮中使用 js ajax 打开一个新标签
- php - PHP 脚本不会更新数据库
- javascript - 如果鼠标被拖动到按钮内的 SVG 图标上,则悬停时的声音会播放双倍
- python - Plotly 和 d3.js 拖动形状
- java - 不兼容的类型 - 无法转换为 java.lang.Class
- google-bigquery - 如何将 Avro 架构中的 ENUM 转换为 BigQuery 的输入?
- json - 使用附加到一个列表中的多个 API GET 结果创建数据框