C++ function

简单记录下编写代码时遇到的问题:

在调用一个接口的时候,需要传入一个std::function类型的参数。

之前在调用此接口时传入的参数lambda表达式类型。由于接口的定义为function<void()>类型,而在调用传入参数时,需要遍历数组,处理数组中的成员。若采用lambda的方式,只能通过捕获的方式传值,考虑到作用域和lambda之间的干扰,应采用值捕获的方式。代码看起来像这样:

void deal(const function<void()>& func) {
    func();
}
int main(int argc, char* argv[]) {
    vector<int> nums = { 1,2,3,4 };   
    for (auto num:nums) {
        auto func = [num]() {
            cout << num << endl;
        };
        deal(func);
    }
    return 0;
}

实际的处理func处理过程很复杂,将lambda表达式在for循环中定义,代码段过长。而且此函数是多次定时调用,涉及到内存分配, 采用lambda需要每次重新分配内存,每次使用完之后释放,效率较低。

改为使用仿函数,则代码如下:

class A {
public:
    A(int num):_num(num) {}
    void operator()() {
        std::cout << _num << std::endl;
    }
private:
    int _num;
};

void deal(const function<void()>& func) {
    func();
}
int main(int argc, char* argv[]) {
    vector<int> nums = { 1,2,3,4,5,6 };   
    for (auto num:nums)
    {
        A a(num);
        deal(a);
    }
    return 0;
}

需要注意的是:

在构造function时,会对仿函数进行拷贝构造和移动构造,在VS2019中的实现如下:

    template <class _Fx, typename _Mybase::template _Enable_if_callable_t<_Fx&, function> = 0>
#else // ^^^ _USE_FUNCTION_INT_0_SFINAE // !_USE_FUNCTION_INT_0_SFINAE vvv
    template <class _Fx, class = typename _Mybase::template _Enable_if_callable_t<_Fx&, function>>
#endif // _USE_FUNCTION_INT_0_SFINAE
    function(_Fx _Func) {
        this->_Reset(_STD move(_Func));
    }

即:在构造function时,先按值传递仿函数对象,调用一次拷贝构造函数,在function函数内部再调用移动构造函数。实现仿函数时,若涉及到内存申请释放,应自定义拷贝构造函数和移动构造函数,避免浅拷贝引起的问题。

编译器默认生成的拷贝构造函数和移动构造函数相关问题参见:

https://www.cnblogs.com/yajiu/articles/15435277.html

 

posted @ 2021-11-30 00:29  亚九  阅读(385)  评论(0编辑  收藏  举报