函数、operator()和lambda

以下言论基于一些臆测

C++中的函数和C的用法是一样的,它能存储的状态只有static变量,

这显然不够自由,比如我想内部使用函数但不希望暴露实现

int _func(int &status) {
    return status ^= 1;
    // 假想实际中整个流程很长,不得不分开用(很多个)函数来实现
}
void func() { // 实现一个`func()`,每次都01010的返回
    static int status = 1;
    return _func(staus);
}

这样供内部使用的_func()不仅破坏了封装性,还不知道调用会发生什么事

如果想要设计多个类似的函数,也显得很冗余(比如我想从1开始)


operator()的重载使得一个对象具有行为类似函数的特性,它所拥有的成员变量和成员函数,都可以作为它的状态,并且封装完好,行为甚至可依靠构造函数来决定,避免了上述的麻烦

class fake_function {
private:
    int status;
    int inner_func() {
        return status ^= 1;
    }
public:
    int operator()() {
        return inner_func();
    }
    fake_function(int status = 1) : status(status) {}
};

int main() {
    auto func = fake_function(0);
    // 还享受了构造函数的便利,其它函数做得到吗.gif
    for(int i = 0; i < 5; i++) cout << func() << endl;
    return 0;
} 

lambda作为语法糖,可以使用operator()的重载作为一种实现机制(并没有考察是否真的这样)

对于捕获列表[]的实现,其实就是生成一个引用进行绑定(&),或者每次调用时通过该引用再生成一个副本(=)(本来觉得是const&,但如果是mutable的话是可修改的,至少应该是个额外的副本,每次调用的时候再通过引用拷贝过去就能做到实时获得捕获当前局部变量的效果),而这些都作为该函数对象的成员来存储,operator()里头的东西就是常规的实现

另外也大概也明白了为什么lambda的类型会这么含糊不清,毕竟本来就不知道它作为类的名称

另另外对于lambda的合成移动、析构这类的操作,应该是与捕获列表的成员有关

发表评论

电子邮件地址不会被公开。 必填项已用*标注