c++ - 在基于 C++ 范围的 for 循环中,begin() 可以返回对不可复制迭代器的引用吗?
问题描述
更新:
感谢所有提交答案的人。
简而言之,答案是返回的“迭代器”begin()
必须end()
是可复制的。
Artyer 提出了一个很好的解决方法:创建一个包含对不可复制对象的引用(或指针)的迭代器类。下面是示例代码:
struct Element {};
struct Container {
Element element;
struct Iterator {
Container * c;
Iterator ( Container * c ) : c(c) {}
bool operator != ( const Iterator & end ) const { return c != end.c; }
void operator ++ () { c = nullptr; }
const Element & operator * () const { return c->element; }
};
Iterator begin () { return Iterator ( this ); }
Iterator end () { return Iterator ( nullptr ); }
};
#include <stdio.h>
int main () {
Container c;
printf ( "main %p\n", & c .element );
for ( const Element & e : c ) { printf ( "loop %p\n", & e ); }
return 0;
}
原始问题:
以下 C++ 代码将无法编译(至少g++
在 Ubuntu 20.04 上的 9.3.0 版本中无法编译)。
错误信息是:
use of deleted function 'Iterator::Iterator(const Iterator&)'
基于该错误,我是否正确得出结论“迭代器”返回begin()
并且end()
必须是可复制的?或者有什么方法可以使用通过引用返回的不可复制的迭代器?
struct Iterator {
Iterator () {}
// I want to prevent the copying of Iterators, so...
Iterator ( const Iterator & other ) = delete;
bool operator != ( const Iterator & other ) { return false; }
Iterator & operator ++ () { return * this; }
Iterator & operator * () { return * this; }
};
struct Container {
Iterator iterator;
Iterator & begin() { return iterator; }
Iterator & end() { return iterator; }
};
int main () {
Container container;
for ( const Iterator & iterator : container ) {}
// The above for loop causes the following compile time error:
// error: use of deleted function 'Iterator::Iterator(const Iterator&)'
return 0;
}
解决方案
是的,迭代器必须是可复制的。这是因为范围迭代在逻辑上等价于以下代码:
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
这是 C++11 版本。C++17 及更高版本略有不同,但根本原因是相同的:__begin
and __end
areauto
和 notauto &
或类似的东西。它们是非引用类型。“begin_expr”和“end_expr”,在很多话中,是最终调用您的自定义and的begin
and表达式。end
begin()
end()
即使您的begin()
和end()
返回引用,它们也会被分配给非引用类型,因此必须是可复制的。
请注意,即使不是这种情况,显示的实现也不是很有用,因为两个引用总是相同的对象,所以 begin 和 end 表达式最终将是相同的对象,并且总是比较相等 (希望)。
推荐阅读
- php - 我想从 Laravel 的存储文件夹中下载多个文件
- tensorflow - 有没有一种方法可以跟踪模型何时提前停止而不实际提前停止?
- r - gtrendsR 统计区域与什么相关?
- c# - 尝试在英特尔 630 HD 上使用 DXGI 和 DirectX11 捕获桌面时出错
- nullpointerexception - 运行 Liquibase 时出现意外错误:未知原因引发 NPE
- python - 包含 python.h 文件时遇到问题
- javascript - 如何使用 JS 路径获得启动点击以点击下一页?
- javascript - p5js '行不是函数'
- c++ - 我的 C++ 源代码在第一次之后无法运行,这是怎么回事?
- python - 如何在另一个列表中访问、编辑和保存列表的文本?