Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解STL中的函子 从《NM JouthIS》第5.9条引用“C++标准库”_C++_Stl_Functor_Function Object - Fatal编程技术网

理解STL中的函子 从《NM JouthIS》第5.9条引用“C++标准库”

理解STL中的函子 从《NM JouthIS》第5.9条引用“C++标准库”,c++,stl,functor,function-object,C++,Stl,Functor,Function Object,for_each()的第二个调用使用相同的功能来添加第一个元素的值 每一个元素。它使用第一个元素初始化AddValue类型的临时函数对象 藏品目录: for_each (coll.begin(), coll.end(), AddValue (*coll. begin()) ) ; 添加第一个元素后,输出如下所示: 22 23 24 25 26 27 28 29 30 我不明白的是,在第二种情况下,为什么输出不是 22 34 35 36 37 38 39 40 41 意思是每次调用都会创

for_each()的第二个调用使用相同的功能来添加第一个元素的值 每一个元素。它使用第一个元素初始化AddValue类型的临时函数对象 藏品目录:

for_each (coll.begin(), coll.end(), AddValue (*coll. begin()) ) ; 
添加第一个元素后,输出如下所示:

22 23 24 25 26 27 28 29 30

我不明白的是,在第二种情况下,为什么输出不是

22 34 35 36 37 38 39 40 41

意思是每次调用都会创建一个新的functor,还是每次调用都会使用该functor?

是的,这就是您所说的。默认情况下,函子是按值传递的,因此它们在std::for_的代码中被复制。但是,您可以编写自己的std::for_版本,每个版本都明确声明希望通过引用传递functor。

是。一个新的函子副本将为每个\u传递。您正在阅读的书对此进行了解释。

表达式
AddValue(*coll.begin())
创建一个类
AddValue
的临时对象。然后将该临时值传递给每个函数的
for_each
然后调用对象的函数调用操作符-即,
操作符()
-从
coll.begin()
coll.end()
的每个元素调用一次


从技术上讲,
for_each
按值获取函子参数(不是引用),因此它实际上是在临时变量的副本上操作的,而不是临时变量本身。

我相信函子像这样被复制的原因是为了使
for_each
更通用

想象一个通过引用获取函子的实现。如果函子是一个右值(例如,如果它是从另一个函数返回的),则会中断:

当然,在这些情况下,算法可以通过常量引用获取函子(因为它们可以绑定到右值),但是函子必须是常量


唯一真正通用的解决方案是按值传递函子。然后它与常量、非常量、右值和左值函子一起工作。

您的
AddValue
构造函数接受
int
,因此当您从
*coll.begin()
构造它时,集合的第一个成员的值将用于初始化成员变量

现在这是固定的(没有任何其他内容会修改值),因此每次从这个
AddValue
对象或这个
AddValue
对象的任何副本使用
value
时,它仍将具有与初始化时相同的值


这是
*coll.begin()
在构建第一个
AddValue
对象时所具有的值,而不是
*coll.begin()
可能已修改为的值。

[Edit]我最初误解了作者的初衷。我改正了错误

对于每个(coll.begin(),coll.end(), AddValue(*coll.begin())

之后,输出如下所示 添加第一个元素:

22 23 24 25 26 27 28 29 30

我不明白的是 第二种情况是为什么输出不是

22 34 35 36 37 38 39 40 41

意思是正在创建一个新的函子 对于每个调用或是否使用函子 每次通话

首先,不管for_是否复制了传入的函子,每个算法都是无关的。与此相关的是,您应该存储指向第一个元素的迭代器或指针,而不是指针对象。如果您这样做,并且每次都取消引用它,那么它应该会起作用

struct AddValue 
{
    const int* ptr;
    explicit AddValue(const int* iptr): ptr(iptr) {}
    void operator() (int& elem) const {elem += *ptr; }
};

int main()
{
    vector<int> v;
    for (int j=1; j <= 9; ++j)
        v.push_back(j + 10);
    for_each(v.begin(), v.end(), AddValue(&v[0]) );
    // v will be [22 34 35 36 37 38 39 40 41]
}
struct AddValue
{
常数int*ptr;
显式AddValue(const int*iptr):ptr(iptr){}
void运算符()(int&elem)常量{elem+=*ptr;}
};
int main()
{
向量v;

对于(int j=1;j您能提供一个章节参考吗?我有点困惑。第8章更详细地解释了函数对象、谓词以及您可以依赖或不依赖的行为。例如,对于谓词,您永远无法确定您的谓词对象将被复制多少次。实际上,我对您的问题感到困惑。您为什么这样做除了22 34 35…?是的。但问题是为什么在每次调用中不重新创建新对象,重复使用同一对象?是为了某种并行性吗?在这种情况下,函子本身是否被复制是学术性的;它存储的是它构造时使用的值的面,而不是引用(或指针)它是用什么构造的,这会导致实际行为和Egon似乎期望的行为之间的差异。Egon-记住,对于_,每个函数都只是一个标准函数,而不是某种宏。一旦计算了它的输入值,它们就会传递给函数,并且是不可更改的。第三个参数t to for_each只是一个对象实例,它不是创建函子的lambda。for_each(a,b,c)不会(也不能)说,“对于[a,b]的每个元素,使用c的文本创建一个新的函子,并将元素传递给新的函子。”它说,“对于[a,b]范围内的每个元素,将元素传递给特定的函子实例c。”不过,在这种情况下,函子本身是否被复制并不重要,更重要的是它将
存储为
int
(即
*coll.begin()
)的副本,而不是
int&
,这意味着它的值在
AddValue
构造时是固定的。
22 34 35 36 37 38 39 40 41
std::for_each(first, last, get_functor(...))
struct AddValue 
{
    const int* ptr;
    explicit AddValue(const int* iptr): ptr(iptr) {}
    void operator() (int& elem) const {elem += *ptr; }
};

int main()
{
    vector<int> v;
    for (int j=1; j <= 9; ++j)
        v.push_back(j + 10);
    for_each(v.begin(), v.end(), AddValue(&v[0]) );
    // v will be [22 34 35 36 37 38 39 40 41]
}