std::vector: vec.data() or &vec[0]

std::vector: vec.data() or &vec[0]

本文关键字:vec or vector data std      更新时间:2023-10-16

当你想访问一个 std::vector 作为 C 数组时,你可以从至少四种不同的方式中进行选择,如你在这个例子中看到的:

#include <iostream>
#include <vector>
using namespace std;
int main() {
  std::vector<int> vec;
  vec.push_back(1);
  vec.push_back(2);
  vec.push_back(42);
  vec.push_back(24024);
  {
    int* arr = vec.data();
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
  {
    int* arr = &vec.front();
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
  {
    int* arr = &vec[0];
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
  {
    int* arr = &vec.at(0);
    cout << arr << endl; /* output: 0x9bca028 */
    cout << arr[3] << endl; /* output : 24024 */
  }
}

在大多数情况下,我发现的是&vec[0]。我认为这是最不优雅的,所以...为什么它是最常用的?是更高效还是更兼容?我找不到很多关于data()的文档.

data()

C++11来说是全新的,这就是为什么你不经常看到它。 我甚至从未想过使用&vec.front()的想法,可能是因为我使用operator[]的频率比front()高得多(几乎从不)。 我想其他人也是如此。

如果您使用的是C++11,那么使用data()绝对是可取的。 特别是,如果向量为空,则使用其他两个选项中的任何一个都会产生未定义的行为! 如果您没有使用 C++11,并且向量可能为空,请务必检查该条件。

使用 &vec[0] 是最常见的,尽管我同意,看起来确实有点奇怪。未来要记住的一件事。如果你的向量恰好是对象的向量,其类重载了运算符&(),请注意,如果你调用 &vec[0],这将导致奇怪的行为。

这不会获取内部连续对象数组中第一项的起始地址,它将返回任何 vec[0].operator&() 将返回的内容。大多数(如果不是全部)这不是您要查找的地址(绝地挥手)。

一个很好的例子是ATL的CComPtr。它重载运算符&(),因此将其存储在向量中可能会有问题。为了解决这个问题,ATL有一个CAdapt模板类,可用于隐藏CComPtr上的运算符&()

在 C++11 std::array之前,我会说 std::vector 是最常用的容器,而不是 C 样式数组。[]运算符通常意味着恒定时间访问(这就是std::vector的全部内容),因此大多数编码人员通常选择这种样式来反映类似数组的访问和行为。

data

()已经成为std::string的一部分已经有一段时间了,所以你可以阅读它。我发现 std::vector 中的 data() 实现是相似的。我偶尔会使用 data() 将std::string视为原始字节数组。