【问题标题】:Why is std::for_each a non-modifying sequence operation?为什么 std::for_each 是非修改序列操作?
【发布时间】:2010-10-14 08:28:37
【问题描述】:

我刚刚在 C++ 标准中读到 std::for_each 是一个非修改序列操作,还有 findsearch 等等。这是否意味着应用于每个元素的函数不应该修改它们?这是为什么?可能会出什么问题?

这是一个示例代码,其中修改了序列。你能看出它有什么问题吗?

void foo(int & i)
{
    i = 12;
}

int main()
{
    std::vector<int> v;
    v.push_back(0);

    std::for_each(v.begin(), v.end(), foo);
    // v now contains 12
}

我怀疑这只是一个解释问题,但我想听听您对此的看法。

PS:我知道我可以使用std::transform 代替for_each,但这不是重点。

【问题讨论】:

    标签: c++ stl standards foreach


    【解决方案1】:

    很简单,您不能进行可能修改容器结构的更改。这是因为在一般情况下,修改容器会使正在使用的迭代器失效。

    只要不改变容器的结构(比如容器中元素的顺序),就可以修改元素。

    [加法]


    请注意,for_each 是一种“非修改”算法似乎有些混淆。 Stroustrup 在“The C++ Programming Language, 3rd Ed”第 4 次印刷的勘误表中总结了这种令人困惑的情况。 (CPL) 关于for_each 是否可以修改序列的元素 (http://www.research.att.com/~bs/3rd_printing5.html) 有这样的说法:

    for_each() 算法被归类为非修改算法,因为它没有显式修改序列。但是,如果应用于非常量序列 for_each() 可能会更改序列的元素。例如,请参阅在 11.9 中使用 negate()。” (最近的标准决议)。

    CPL 最初表明传递给for_each 的函数或函数对象不允许修改传递给它的元素。但是,CPL 是在标准最终确定之前编写和最初发布的,显然对for_each() 的限制在最终确定之前就被删除了。

    另见:

    【讨论】:

      【解决方案2】:

      我认为“非修改序列操作”意味着该操作不修改序列。但是操作可以修改容器元素

      容器元素和序列的值 - 不同的东西。

      【讨论】:

        【解决方案3】:

        this defect report他们说

        LWG 认为标准中没有任何内容禁止修改序列元素的函数对象。问题是 for_each 在名为“非变异算法”的部分中,并且标题可能令人困惑。非规范性说明应阐明这一点。

        但也要注意this one

        他们似乎称其为“非修改”,因为 for_each 本身并没有显式修改序列的元素。

        【讨论】:

        • 是的,我刚刚找到了相同的问题列表。正如我所想的,这只是一个解释问题(但我真的认为他们应该添加这个澄清说明)。
        • 是的,我也这么认为。它还没有在n2800中。让我们看看下一个草案包含什么。由于该便笺具有 CD1 状态,因此很奇怪,它不再存在 :) 我怀疑他们将其删除是因为他们想为它制定一个概念。
        • 不错的发现!在缺陷报告中特别注意这一点:“Stepanov 和 Lee 的原始 STL 文档明确禁止函数对象修改其参数”。我没有意识到这一点。
        【解决方案4】:

        如上所述,for_each 被归类为“非变异算法”

        STL 的“变异”对应物是 std::transform。

        既然你表明你知道你可以使用 std::transform,那么上面确实成为了重点。它是与阅读您的代码的人交流的一个点。

        如果我看到 std::for_each,很明显,无论 foo 做什么,它都不会修改容器。

        可以说明我遵循的准则:

        "如果你希望使用容器的元素来完成一些不改变元素的任务,请使用 std::for_each。

        如果您希望使用容器的元素以某种系统方式修改元素,或者在以某种方式更改它们的任务中使用它们,请使用 std::transform。"

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多