我刚读在C++标准std::for_each
是一个非修改序列操作,具有沿find
,search
等等.这是否意味着应用于每个元素的函数不应该修改它们?这是为什么?什么可能出错?
这是一个示例代码,其中修改了序列.你能看到它有什么问题吗?
void foo(int & i) { i = 12; } int main() { std::vectorv; v.push_back(0); std::for_each(v.begin(), v.end(), foo); // v now contains 12 }
我怀疑这只是一个解释问题,但我想对此有所了解.
PS:我知道我可以用std::transform
而不是for_each
,但那不是重点.
很简单,您无法进行可以修改容器结构的更改.这是因为在一般情况下,修改容器会使正在使用的迭代器无效.
只要不改变容器的结构(例如容器中元素的顺序),就可以修改元素.
[加成]
请注意,似乎存在一些关于for_each
作为"非修改"算法的混淆.Stroustrup在第四版"C++编程语言,第3版"的勘误表中总结了这种令人困惑的情况.(CPL)有关于是否for_each
可以修改序列元素的说法(http://www.research.att.com/~bs/3rd_printing5.html):
"该
for_each()
算法被归类为非修改,因为它没有明确地修改序列.但是,如果应用于非const序列,则for_each()
可能会更改序列的元素.例如,请参阅negate()
11.9中的使用." (最近的标准解决方案).
CPL最初表示传递给的函数或函数对象for_each
不允许修改传递给它的元素.然而,CPL是在标准最终确定之前编写并最初发布的,显然这个限制在for_each()
最终确定之前被删除了.
也可以看看:
http://www.angelikalanger.com/Articles/Cuj/03.ForeachTransform/ForEachTransform.html
litb的答案中提到的C++ LWG缺陷报告(http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#475)
请参阅他们所说的缺陷报告
LWG认为标准中没有任何内容禁止修改序列元素的函数对象.问题是for_each是一个名为"非突变算法"的部分,标题可能令人困惑.一份非规范性说明应澄清这一点.
但也要注意这个.
他们似乎称之为"非修改",因为for_each本身并不会明确地修改序列的元素.
我认为"非修改序列操作"意味着此操作不会修改序列.但是操作可以修改容器元素.
容器元素和序列的价值 - 不同的东西.