带有transform的for_each出现意外行为

Unexpected behaviour of for_each with transform

本文关键字:意外 each transform for 带有      更新时间:2023-10-16

当我用std::transform取消注释注释行时,上面的for_each将不会打印任何内容。下面的for_each也不打印任何内容。我认为代码会从v中提取元素,增加它们并将它们插入v2中。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(const int& what){
    cout<<what<<" ";
}
int change(const int& from){
    return from+1;
}
int main() {
    vector<int> v(5,10);
    vector<int> v2;
    for_each(v.begin(),v.end(),print);
    //transform(v.begin(),v.end(),v2.begin(),change);
    for_each(v2.begin(),v2.end(),print);
    return 0;
}

您的第二个集合是空的——要向其中插入项,您需要使用std;:back_inserter:

transform(v.begin(), v.end(), back_inserter(v2), change);

然而,请注意,for_each在这里也不是真正的最佳选择。如果你要使用标准算法,我建议复制到ostream_iterator:

copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
transform(v.begin(), v.end(), back_inserter(v2));
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

如果你真正想做的只是在输入中的每一项中添加一个,你可能会发现使用std::plus之类的东西比自己编写代码更容易(或者,如果你有C++11,你可以使用lambda)。

为了回答您实际提出的问题(为什么当您按原样执行transform时,这些问题都不起作用):您有未定义的行为试图访问当前边界之外的向量。因此,任何行为都是允许的。在UB被实际调用之前,通常很难看到程序中的UB稍后会如何影响代码的行为,但标准非常明确地允许这样做。一些编译器利用这一点来实现优化(例如),否则这些优化是不可能的。

std::transform的目标范围必须足够大,以容纳结果。您的v2是一个空向量。您可以在调用std::transform之前调用v2.resize(),也可以像这样使用back_inserter

transform(v.begin(),v.end(),back_inserter(v2),change);