为什么在C++11的范围内需要按值捕获 这里是一个C++基于范围的循环示例,它通过值捕获元素 vector<int> v = {1, 3, 5, 7, 9}; for (auto x : v) cout << x << ' ';

为什么在C++11的范围内需要按值捕获 这里是一个C++基于范围的循环示例,它通过值捕获元素 vector<int> v = {1, 3, 5, 7, 9}; for (auto x : v) cout << x << ' ';,c++,c++11,C++,C++11,更多 我的问题 为什么甚至允许按值捕获?它只是让人困惑和容易出错。如果你犯了错误,你会付出很多代价。我无法想象任何不能通过显式地创建一个副本而不是循环来解决的问题。有什么具体原因吗?我是不是遗漏了什么 编辑 是的,我知道函数允许传递值,但这有一个明显的好处。我要问的是,在for循环中是否有使用按值捕获的功能。我现在可以看到,这可能是有用的布尔和字符序列 与我们可以按值传递参数的原因完全相同-如果需要副本,请按值获取 我无法想象任何不能通过显式地创建一个副本而不是循环来解决的问题 我认为这是你面

更多

我的问题 为什么甚至允许按值捕获?它只是让人困惑和容易出错。如果你犯了错误,你会付出很多代价。我无法想象任何不能通过显式地创建一个副本而不是循环来解决的问题。有什么具体原因吗?我是不是遗漏了什么

编辑


是的,我知道函数允许传递值,但这有一个明显的好处。我要问的是,在for循环中是否有使用按值捕获的功能。我现在可以看到,这可能是有用的布尔和字符序列

与我们可以按值传递参数的原因完全相同-如果需要副本,请按值获取

我无法想象任何不能通过显式地创建一个副本而不是循环来解决的问题

我认为这是你面临的主要问题。循环不是为你做的。这是明确要求一份副本。还有什么比初始化非引用变量更显式的呢

这实际上只是一个正常的声明。为什么,当它在其他地方都有效时,我们会让汽车本身在这里无效?事实上,本标准将该声明的初始化定义为:

auto x = *__begin;
其中_begin是一个表达式,在本例中为范围的第一个元素提供迭代器v.begin。这与C++中的其他复制没有什么不同。你认为以下是一个常见的错误吗?
int x = some_other_int;
或:

不,我们需要副本时会写这样的声明

下面是一个示例用例:

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);
}

我认为部分混乱是由于使用自动,这是常见的,尽管不是强制性的。基本上,基于范围的类型var:range意味着:迭代范围中的元素,创建一个使用范围中相应元素初始化的类型为的局部变量var。根据标准的规定,此结构具有常规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声明可以是扩展版本和编译版本上可以替换的任何内容。对于for范围声明中的类型没有任何要求,它甚至可能与range init所持有的类型不同:

因为可以使用任何允许编译扩展的类型,所以允许使用auto,其语义与任何其他上下文中的语义完全相同,其行为与所有其他情况下的行为完全相同


将基于范围的for的要求更改为只允许通过引用进行迭代将不必要地使语言标准的措辞和编译器无法扩展的实现复杂化,因为for范围声明将不仅仅是一个声明,但是一种限制值使用的形式,实际上限制了需要更复杂用户代码的构造的使用,当需要值时,用户必须手动复制。请记住,这个构造只是为了简化代码,它不是一个启用功能,没有它,这个构造就无法完成任何事情。您可以随时手动生成上面的展开。

vector呢?在这种情况下,参考的开销非常大。此外,这就是汽车的工作原理。@BartekBanachewicz vector FTFY-为什么允许传递值?它怎么比任何其他副本更容易出错?i、 e.int x=v.begin;?你告诉我。为什么传递值有用?问题是。不允许做无用的事情是一种不错的做法。函数的传递值很有用。对你知道这在什么情况下有用吗?有任何用例吗?我得到了一些评论。@stardust_u当您需要元素的副本而不是对它的引用时,它很有用。与通过引用传递参数完全相同。嗯。是的,我认为这更多的是一致性问题,而不是使用问题。好啊我知道了。你为什么要修改x的副本?您创建了vector元素=x的副本,并通过引用将其传递给modify_参数。@stardust_:您似乎认为“通过值”在某种程度上是有用的,但实际上并非如此。怎样您总是可以通过引用传递函数,并让实现在需要时进行复制,对吗?这不是你对循环的建议吗?在函数内部执行与在循环中执行有何不同?
// 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
  }
}
// Convoluted example:
void printFloor(std::vector<double> const & v) {
   for (int i : v) {
       std::cout << ' ' << i;
   }
}