在c++中迭代一个向量时,我注意到标准库中有一个begin()
函数,还有一个作为vector
类成员函数的begin()
。如果有的话,两者之间的区别是什么,应该使用哪一个?
示例:
vector<int> numbers;
//Code to put values in my vector
for (vector<int>::iterator i = numbers.begin(); i < numbers.end(); i++)
cout << *i << 'n';
vs:
vector<int> numbers;
//Code to put values in my vector
for (vector<int>::iterator i = std::begin(numbers); i < std::end(numbers); i++)
cout << *i << 'n';
std::begin()
是在C++11中添加的,以便更容易地编写通用代码(例如在模板中)。最明显的原因是普通C样式数组没有方法,因此没有.begin()
。因此,您可以将std::begin()
与C样式数组以及具有自己的begin()
和end()
的STL样式容器一起使用。
如果您编写的代码不是模板,则可以忽略std::begin()
;如果你突然因为它是新的而开始在任何地方使用它,你的程序员同事可能会觉得很奇怪。
向量的std::begin()
的实现只调用std::vector<T>::begin()
,因此在这种确切的情况下,两者之间没有区别。
std::begin()
在通用算法中发挥作用:
template<typename Container>
void my_algorithm(Container c) {
using std::begin;
using std::end;
auto const start = begin(c); // ADL will find the appropriate overload
auto const finish = end(c);
// ... rest of code ...
}
如果编译器优化了代码,那么使用哪一个并不重要。否则,您可能需要使用更OOP的格式:numbers.begin()
此代码已插入用于速度测量的快速工作台:
std::vector<int> arr = {0,1,2};
static void formatA(benchmark::State& state) {
for (auto _ : state) { // Code inside this loop is measured repeatedly
std::vector<int>::iterator itrA = arr.begin(); // arr.end();
benchmark::DoNotOptimize(itrA);
}
}
// Register the function as a benchmark
BENCHMARK(formatA);
static void formatB(benchmark::State& state) {
for (auto _ : state) { // Code before the loop is not measured
std::vector<int>::iterator itrB = begin(arr); // end(arr);
benchmark::DoNotOptimize(itrB);
}
}
BENCHMARK(formatB);
所有这些都是使用STL=libstdc++(GNU)编译的,begin()
的结果如下:
formatA | formatB | 结论 | |
---|---|---|---|
optim=none compiler=Clang 11.0 std=c++11 | 2.1914 | 5.1870 | A比B快2.4倍 |
optim=none compiler=Clang 15.0 std=c++20 | 2.0666 | 2.8974 | A比B快1.4倍 |
optim=O3 compiler=Clang 11.0 std=c++11 | 1.10941.0130 | 大致等效的运行时 (等效程序集) | |
optim=O3 compiler=Clang 15.0 std=c++20 | 1.0093 | 1.0007 | 大致等效的运行时 (等效程序集) |