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

36

当你想把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()的很多文档。


1
data() 可能被认为是不兼容的,因为它是 C++11 的(这解释了文档稀缺的原因,因为主要的文档来源正在适应新功能),但时间肯定会消除这种不兼容性,然后它就是明确的选择。 - Christian Rau
5个回答

25

data()是C++11中全新的,因此你不会经常看到它。我从来没有想过使用&vec.front(),可能是因为我更常使用operator[]而不是front()(几乎从不使用)。我想其他人也是一样的。


10
不。它的添加恰好是为了让人们不必编写 v.empty()?NULL:&v[0] - bames53
@MooingDuck 我的示例已经编译并运行,正如您所看到的,data() 返回一个非 const 指针。 - Alessandro Pezzato
所以data()不兼容旧版C++? - Alessandro Pezzato
@AlessandroPezzato:是的,这就是我说我很难证明它的原因。它可能是一个早期采用的扩展。我手头没有C++03官方标准。但我可以参考一些旧的、半可靠的来源,比如这里或者这本书。 - Benjamin Lindley
1
data()在libstdc++的向量中已经是一个非标准扩展了一段时间。现在它已经成为C++11标准的一部分。 - Dave S
显示剩余3条评论

23

如果您正在使用C++11,那么使用data()肯定更可取。特别是,如果向量为空,则使用另外两个选项会导致未定义的行为!如果您没有使用C++11,并且该向量可能为空,请确保检查此条件。


6
使用 &vec[0] 是最常见的方法,尽管我同意,它看起来有点奇怪。未来需要记住一件事情。如果您的向量恰好是对象的向量,而这些对象的类重载了 operator&(),那么如果您调用 &vec[0],这将导致奇怪的行为。
它不会获得对象内部连续数组中第一项的起始地址,它将返回 vec[0].operator&() 将返回的任何内容。大多数情况下,这不是您要查找的地址(Jedi 手势)。
ATL 的 CComPtr 是一个很好的例子。它重载了 operator&(),因此将其存储在向量中可能会有问题。为了解决这个问题,ATL 有一个 CAdapt 模板类,可以用于隐藏 CComPtr 上的 operator&()。

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

1

data() 函数已经成为 std::string 的一部分了,所以你可能需要了解一下。我发现 std::vector 中的 data() 实现类似。我偶尔使用 data() 将 std::string 视为原始字节的数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接