【问题标题】:What is the difference between &vector[0] and vector.begin()?&vector[0] 和 vector.begin() 有什么区别?
【发布时间】:2015-05-28 15:24:27
【问题描述】:

这个问题与 Effective stl book 的第 16 项有关,该书指出,在旧代码中使用向量(假设vector<int>vec)而不是数组时,我们必须使用 &vec[0] 而不是 vec.begin() :

 void doSomething(const int* pInts, size_t numlnts);  
 dosomething(&vec[0],vec.size()); \\correct!! 
 dosomething(vec.begin(),vec.size()); \\ wrong!! why??? 

这本书指出 vec.begin()&vec[0] 不同。为什么 ?两者有什么区别?

【问题讨论】:

  • vector::begin() 产生一个迭代器, &vec[0] 产生一个指针。不是一回事。
  • 但是迭代器是一个指针,不是吗?
  • 指针是一种迭代器,但还有许多其他类型的迭代器不是指针。例如,虽然经常使用相同的术语,但通常说迭代器“指向”某个对象时引用您在取消引用迭代器时获得的对象。
  • @AyushChaurasia:没有。

标签: c++ vector


【解决方案1】:

std::vector 是封装动态大小数组的序列容器。这使您可以方便地存储一堆元素,而无需担心管理作为元素存储的底层数组。使用这些类的便利很大一部分来自于它们为您提供了一堆方法,让您无需处理原始指针即可处理序列,迭代器就是一个例子。

&vec[0] 是指向向量正在使用的底层存储的第一个元素的指针。 vec.begin() 是一个 iterator,它从向量的开头开始。虽然这两个都为您提供了访问序列中元素的方法,但它们是两个不同的概念。搜索迭代器以更好地了解其工作原理。

如果您的代码支持iterators,通常最容易使用迭代器来迭代数据。造成这种情况的部分原因是迭代器不是指针,它们让您可以迭代数据结构的元素,而无需了解您正在迭代的数据结构的实现细节。

但是,有时您需要原始的项目数组,例如在某些遗留 API 或对 C 代码的调用中,您可能需要将指针传递给数组。在这种情况下,您别无选择,只能从向量中提取原始数组,您可以使用诸如 &vec[0] 之类的东西来执行此操作。请注意,如果您有 c++11 支持,则可以使用std::vector::data 进行此操作,这将使您能够访问底层存储阵列。 c++11 方式还有一个额外的好处,那就是更清楚地向阅读您的代码的人说明您的意图。

【讨论】:

  • 他们不是。将迭代器视为指针周围的包装器(类)。你不能像这样获取类对象的地址。类(迭代器)促进功能,以便您可以像使用指针一样使用它们。
  • "请问迭代器和指针有什么区别?" "" "但是迭代器和指针不一样吗?" 什么
【解决方案2】:

形式上,一个产生一个迭代器,另一个产生一个指针,但我认为主要区别在于如果向量为空,vec[0] 会做坏事,而vec.begin() 不会。

【讨论】:

  • 获取vec[0] 的地址即使对于空数组也是合法的。您可以指向数组末尾之外的一个元素,但不能取消引用该指针。
  • @b4hand 对于 array 是正确的,但是 OP 特别提到它是一个 vector,不是吗?我错过了什么吗?
  • @b4hand A std::vector 不是数组。 vector::operator[] 返回一个引用,它必须绑定到一个实际的对象。 (或者,使用序列容器要求:vector::operator[] 必须表现得好像它执行迭代器的间接。)
  • @dyp:我认为他可能在引用旧的“&a[n] 是安全的,因为&* 取消”废话。
  • 对旧评论的回复很晚,但是是的,我只是在谈论一个数组,因此该评论在上下文中是不正确的。 vec[0] 对于空数组是合法的,对于空向量是不合法的。我认为如果不是“会做坏事”,而是说“如果向量为空,vec[0] 会导致未定义的行为”,这可能是一个更好的答案。具体来说,我会对此表示赞成,因为它添加了其他答案未提及的信息。
【解决方案3】:

vec.begin() 的类型为 std::vector<int>::iterator&vec[0] 具有指向 std::vector<int>::value_type 的类型指针。它们不一定是同一类型。

给定的实现可能使用指针作为向量的迭代器实现,但这不能保证,因此您不应依赖该假设。事实上,大多数实现都提供了一个包装迭代器类型。

关于您关于指针是迭代器的问题,这部分是正确的。指针确实符合随机访问迭代器的标准,但并非所有迭代器都是指针。还有不支持指针随机访问行为的迭代器。

【讨论】:

  • "这些不一定是同一类型。" ...afaik 它们永远不是同一类型(即使 std::vector<T>::iterator 只是 T* 的包装器,它仍然是不同的类型)
  • std::vector<T>::iterator 可能只是T* 的类型定义,因此它们是相同的类型。我相信最初的 STL 是使用这种方法构建的;不过,几乎所有现代实现都使用包装类。
  • 你说得对,我花了一些时间来说服自己,但我的 afaik 还是不够远;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-28
  • 1970-01-01
  • 2020-12-27
  • 2016-03-23
  • 2021-06-16
相关资源
最近更新 更多