std::vector::front()和begin()的区别

6

vector的帮助文档中对front()函数的解释如下:

返回指向容器第一个元素的引用。 与成员函数vector::begin返回指向相同元素的迭代器不同,该函数直接返回引用。

vector的帮助文档中对begin()函数的解释如下:

返回指向容器第一个元素的迭代器。 请注意,与成员函数vector::front返回第一个元素的引用不同,该函数返回一个随机访问迭代器。

以下是代码输出:

char arr[] = { 'A', 'B', 'C' };
vector<char> vec(arr, arr+sizeof(arr));
cout << "address of vec.front() " << (void*)&vec.front() << endl;
cout << "address of vec.begin() " << (void*)&vec.begin() << endl;

vec.front() 00401F90的地址是什么?vec.begin() 0030F494的地址是什么?

我不理解“直接引用”是什么意思?在begin()的情况下,一个随机访问迭代器不就是一个指针吗?

请问有人能指出这两者之间的区别吗?


3
front() 返回元素(例如,'A'),而 begin() 返回一个指向第一个元素的迭代器(因此 *begin() == 'A')。 - chris
请注意,&vec.begin() 不是有效的代码。您的编译器将其作为扩展接受。 - Luc Danton
5个回答

16
根据《C++程序设计语言》16.3.3节中Stroustrup的说法,将front()视为第一个元素,将begin()视为指向第一个元素的指针。

2
我喜欢这个答案的简洁。 - Angus Comber

8

如果begin()不是随机访问迭代器,那它不就是一个指针吗?

不,迭代器具有某些指针语义,但它实际上是一个类。

即使是这样,这也应该回答了问题。这就像问为什么指针的地址与其所指向的对象的地址不同。

如果您对迭代器进行解引用,您将获得第一个元素,您将获得相同的值:

&(*vec.begin())

因为

*vec.begin() == vec.front()

1
小修正:在某些情况下,指针被用作迭代器。std::iterator_traits为指针提供了一个专门的实现,而指向数组的指针合法地实现了随机访问迭代器的概念。因此,指针和迭代器的集合之间存在非空交集。但除此之外,答案是正确无误的。 - WeirdlyCheezy

4

对于向量,begin()end()返回随机访问迭代器。它们可能返回普通指针;这是可以的,因为它满足成为随机访问迭代器的要求。特别地,你可以写*begin()来获取序列中第一个对象的引用(假设有一个)。front()给你一个引用到序列中第一个对象,而不需要经过中间迭代器。就像这样:

vector<int> v;
v.push_back(3);
int i = *v.begin(); // i == 3
int j = v.front();  // j == 3

我看到Luchian编辑了Pete的帖子。对于第二个评论,你可能想说“j == 3”(即使显示的评论仍然是正确的,但很可能不是预期的评论)。 - Happy Green Kid Naps

3
假设向量中至少有1个元素:
vec.front()

与之相同

*vec.begin()

0
为了让你的思路更加清晰,始终记住以下两行代码,假设你有一个来自STL的向量叫作v:
v.front() = * v.begin()
&&
v.back() = * v.end()

这意味着如果你有一个向量:

v = {1,2,3,4};

假设你有一个名为IT的迭代器,并且你想要访问第一个和最后一个元素,你可以这样做:

IT = v.begin();
std::cout<<*IT<<std::endl; // output : 1
IT = v.end();
std::cout<<*IT<<std::endl; // output : 4

或者你可以轻松地这样做:

std::cout<<v.front<<std::endl; // output  : 1
std::cout<<v.back<<std::endl; // output  : 4

两者将打印相同的输出,区别只在于您是否想使用迭代器。


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