范围for循环依赖begin和end函数
/*************************************************************************
> File Name: range_for_loop.cc
> Author: hsz
> Brief:
> Created Time: Thu 18 Jan 2024 10:17:04 AM CST
************************************************************************/
#include <iostream>
#include <initializer_list>
/**
* @brief 测试范围for循环释放依赖于begin和end函数
*/
template<typename T, std::size_t SIZE>
class MyArray {
public:
MyArray(const std::initializer_list<T> &arr)
{
int32_t size = arr.size() <= SIZE ? arr.size() : SIZE;
int32_t i = 0;
for (auto it = arr.begin(); i < size; ++i, ++it) {
data[i] = *it;
}
}
T& operator[](std::size_t index) {
return data[index];
}
const T& operator[](std::size_t index) const {
return data[index];
}
T* begin() {
return data;
}
T* end() {
return data + SIZE;
}
private:
T data[SIZE];
};
int main() {
MyArray<int, 5> arr = {1, 2, 3, 4, 5};
for (const auto& element : arr) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
g++ range_for_loop.cc -o range_for_loop
修改begin和end函数名后再次编译,报出以下错误。
range_for_loop.cc: In function ‘int main()’:
range_for_loop.cc:53:32: error: ‘begin’ was not declared in this scope
for (const auto& element : arr) {
^~~
range_for_loop.cc:53:32: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from range_for_loop.cc:8:
/usr/include/c++/7/bits/range_access.h:105:37: note: ‘std::begin’
template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
^~~~~
range_for_loop.cc:53:32: error: ‘end’ was not declared in this scope
for (const auto& element : arr) {
^~~
range_for_loop.cc:53:32: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from range_for_loop.cc:8:
/usr/include/c++/7/bits/range_access.h:107:37: note: ‘std::end’
template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
进一步思考
无论标准库还是其他库,begin和end函数几乎是用于迭代器的实现,而迭代器又要求使用过程中不能修改原有结构。
所以在范围for循环中,不能删除和插入数据。否则,极易产生崩溃问题。
// 错误示例
std::list<int32_t> get_list()
{
static std::list<int32_t> ret;
static int32_t idx = 0;
ret.push_back(idx);
}
for (const auto &it : get_list())
{
std::cout << it << "\n";
}
如果需要在循环过程中修改结构,可以自己使用迭代器进行遍历。
std::list<int32_t> intList = {1, 2, 3, 4, 5};
for (auto it = intList.begin(); it != intList.end(); ) {
std::cout << *it << " ";
if (3 == (*it)) {
it = intList.erase(it);
} else {
++it;
}
}
std::cout << std::endl;
for (const auto &it : intList) {
std::cout << it << " ";
}
std::cout << std::endl;
范围for循环的变量类型不是iterator
std::list<std::string> strList = {"1", "2", "3", "4", "5"};
for (const auto &it : strList) {
std::cout << it << ", " << typeid(decltype(it)).name() << "\n";
}
std::cout << std::endl;
输出以下内容
1, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
2, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
3, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
4, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
5, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE