C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 仿函数如何维护/存储对象的状态大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我是C noob学习仿函数.我有这个代码如下(注意 – 这不是我的功课,我已经过去了!).

它在控制台上打印0 1 2 3 4 5 6 7 8 9
我没看到它是如何保持这个对象的状态(n的值)如果函数是通过值而不是通过引用/指针调用

编辑:
我想到了这里(例1),因为函数被Value调用,构造函数每次都将n初始化为零.因此它应该始终为零,然后它应该@L_673_8@到1并返回1.如何打印0 1 2 3 4 5 6 7 8 9

例1]

class g
{
public:
    g():n(0){}
    int operator()() { return n++; }
    int n;
};

;

int main()
{
    int a[10];
    g v1;
    std::generate(a,a+10,g());//This passes a functor to generate 

    //EDIT - this will print 0 1 2 3 4 5 6 7 8 9**
    std::copy(a,std::ostream_iterator<int>(std::cout," "));

    getchar();
    return 0;
}

因为我已经看到类似下面的代码使用仿函数中的引用变量来保留状态,here并使用以下概念开发了一个简单的代码

例2]

class CounTingFunctor
{
public:
    CounTingFunctor() : _counter(0) {}
    int getCounter(void) const {return(_counter);}
    void operator () (Contained item) {if(item.getShouldBeCounted()) _counter++;}
private:
    int _counter;
};
#endif

//this class uses references to maintain state in the functor
class CounTingFunctor
{
public:
    CounTingFunctor(int &elem) : _counter(elem) {_counter=0;}
    int getCounter(void) const {return(_counter);}
    void operator () (Contained item) {if(item.getShouldBeCounted()) _counter++;}
private:
    int &_counter;
};

int main()
{
    vector<Contained> Container(10);
    Container[3].setShouldBeCounted(false);
    Container[9].setShouldBeCounted(false);
    int elem;
    CounTingFunctor CountAllWhoShouldBe(elem);
    std::for_each(Container.begin(),Container.end(),CountAllWhoShouldBE);
    std::cout << CountAllWhoShouldBe.getCounter() << " items should be counted." << std::endl;

    getchar();
}

问题是

因此,仿函数自己维护对象的状态,即不需要任何参变量,如示例2所示

或者示例1中的代码正常工作,因为Std :: generate()通过引用/指针调用仿函数

进一步阅读材料赞赏.

解决方法

当你调用std :: generate时,它会获得自己的仿函数对象副本.一旦进入该函数,它只是重复调用它自己的对象的单个实例,因此状态保留在generate调用中,但不在generate和调用者之间.

所以,将代码更改为

g v1;
std::generate(a,v1);

之后v1.n仍为零.在内部生成它是在它的本地副本(比如v2)上运行,它确实@L_673_8@了,但是无法告诉v1它.

现在,如果你想将v2的状态传达给v1,那就是当你需要在你的仿函数中使用引用时,所以v1和v2共享在调用中变异的状态.

我们可以扩展通话以更清楚地显示

g v1;
std::generate(a,v1);
// -> generate(begin=a,end=a+10,v2=g(v1))
{
    while (begin != end)
        *begin = v2();
}
// v2 just went out of scope,and took the accumulated state with it!
// v1 in the caller's scope remains unchanged

现在显而易见的是,如果v1不是作为深度复制并在内部保持其状态的值对象,而是保持对共享状态的引用并且被浅层复制,那么v2将与v1共享相同的状态,并且该状态将通话结束后可以访问.

事实上,我们可以编写一个简单的包装器来自动执行此操作,因此您无需为每个仿函数手动执行此操作:

template <typename OriginalFunctor,typename RType>
class StatefulFunctor
{
    OriginalFunctor &fun;

public:
    StatefulFunctor() = delete;
    StatefulFunctor(OriginalFunctor &orig) : fun(orig) {}
    StatefulFunctor(StatefulFunctor const &other) : fun(other.fun) {}
    StatefulFunctor(StatefulFunctor &&other) : fun(other.fun) {}

    template <typename... Args>
    RType operator() (Args&&... args)
    {
        return fun(std::forWARD<Args>(args)...);
    }
};

template <typename RT,typename OF>
StatefulFunctor<OF,RT> stateful(OF &fun)
{
    return StatefulFunctor<OF,RT>(fun);
}

现在将原始代码更改为:

g v1;
std::generate(a,stateful<int>(v1));

意味着v1.i将在适当的位置更新.

正如jerry Coffin指出的那样,即使在通话中保持状态也不能得到保证,因此即使您不需要为呼叫者保留状态,使用状态仿函数执行此类操作也是明智的.

大佬总结

以上是大佬教程为你收集整理的c – 仿函数如何维护/存储对象的状态全部内容,希望文章能够帮你解决c – 仿函数如何维护/存储对象的状态所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。