为什么在 C++11 的范围内需要按价值捕获
Why is capturing by value needed in C++11's range-based for
下面是一个c++基于范围的循环的例子,它通过值
捕获元素vector<int> v = {1, 3, 5, 7, 9};
for (auto x : v)
cout << x << ' ';
更多使用c++ 11' based for的正确方法是什么?
<标题>我的问题
为什么允许按值捕获?它只是令人困惑和容易出错。如果犯了错误,你会付出很大的代价。我想象不出有什么问题不能通过显式地创建一个副本而不是循环来解决。有什么特别的原因吗?我遗漏了什么吗?
编辑是的,我知道函数允许按值传递,但这有一个明显的好处。我想问的是,在for循环中是否有按值捕获的任何用途。我现在可以看到,这可以是有用的bool和char序列。
标题>与我们可以按值传递参数的原因完全相同——如果你需要一个副本,按值接受它。
我想象不出有什么问题不能通过显式地创建一个副本而不是循环来解决。
我认为这是你的主要问题。这个循环并不是"为你做这件事"。这个是显式请求副本。还有什么比初始化非引用变量更显式的呢?
这实际上只是一个普通的声明。为什么,当它在其他地方都有效时,我们要让auto
单独在这里无效?实际上,这个声明的初始化被标准定义为:
auto x = *__begin;
,其中__begin
是表达式,给出了范围的第一个元素的迭代器(在本例中为v.begin()
)。这与c++中的其他复制没有什么不同。你认为以下是一个常见的错误吗?
int x = some_other_int;
或:
std::string str = some_other_string;
不,当想要一个副本时,我们要这样写声明。
下面是一个用例:
void modify_argument(X&);
void use(X);
// ...
std::vector<X> v = /* ... */;
for (auto x : v) {
// We want to modify the copy of x, but not the original:
modify_argument(x);
use(x);
}
我认为部分混淆是由于使用auto
引起的,这是常见的,但不是强制性的。基本上,基于范围的for (type var : range)
意味着:迭代range
中的元素,创建一个type
类型的局部变量var
,用range
中的相应元素初始化。这个结构可以直接转换为标准规定的for循环:
// for (for-range-declaration : range-init)
// statement
{
auto && __range = range-init;
for ( auto __begin = begin-expr, __end = end-expr;
__begin != __end; ++__begin ) {
for-range-declaration = *__begin;
statement
}
}
range-init和for-range-declaration可以是任何可以在扩展版本和编译中替换的内容。对于for-range声明中的类型是什么没有要求,它甚至可以与range-init所保存的类型不同:
// Convoluted example:
void printFloor(std::vector<double> const & v) {
for (int i : v) {
std::cout << ' ' << i;
}
}
因为可以使用任何类型来允许扩展编译,所以允许使用auto
,具有与任何其他上下文中完全相同的语义,并且行为与所有其他情况完全相同。
将基于范围的for的要求更改为只允许通过引用进行迭代,将不必要地使语言(标准措辞)和实现复杂化(编译器不能扩展,因为for-range声明将不仅仅是一个声明,而是一种限制值使用的有限形式),并且实际上限制了在需要值时需要更复杂的用户代码的结构的使用(用户将不得不手动复制)。请记住,这个结构只是为了简化代码,它不是一个启用特性,没有它,没有什么可以用这个结构做的(您总是可以手动生成上面的展开)。
- 为什么在全局范围内使用"extern int a"似乎不行?
- 错误:未在此范围内声明'reverse'
- 并行用于C++17中数组索引范围内的循环
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 不计算一个范围内的完美数
- 错误:"imread"未在此范围内声明
- 我在范围内未声明的错误类有问题
- 如何在cpp中使用地图显示给定日期范围内(在下面的问题中)的费率?
- 我有一个数组,我想输入一个范围,然后找到范围内所有偶数的总和?
- 未在此范围内声明错误 'xy'
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 命名空间范围内的外部 - GCC vs clang vs msvc
- 自动和范围内 for 循环 C++11 不起作用
- 为什么即使在启用 C++11 并且我包含字符串之后,'stod'仍然没有在此范围内声明?
- -O1/2/3 与 -std=c++1y/11/98 - 如果包含,<cmath>我收到错误:"_hypot"未在此范围内声明
- 我们可以擦除c++11中基于循环的范围内的项目吗
- 使用对指针的引用作为循环C++11范围内的序列
- 从矢量中删除项目,而在 C++11 范围内'for'循环?
- C++11范围内的随机数和显式相似性
- c++ 11在块范围内的函数声明用例