• C++笔记--std::相关


    std::packaged_task

    https://www.cnblogs.com/haippy/p/3279565.html

    https://en.cppreference.com/w/cpp/thread/packaged_task

    std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task 与 std::function 类似,只不过 std::packaged_task 将其包装的可调用对象的执行结果传递给一个 std::future 对象(该对象通常在另外一个线程中获取 std::packaged_task 任务的执行结果)。

    std::packaged_task 对象内部包含了两个最基本元素,一、被包装的任务(stored task),任务(task)是一个可调用的对象,如函数指针、成员函数指针或者函数对象,二、共享状态(shared state),用于保存任务的返回值,可以通过 std::future 对象来达到异步访问共享状态的效果。

    可以通过 std::packged_task::get_future 来获取与共享状态相关联的 std::future 对象。在调用该函数之后,两个对象共享相同的共享状态,具体解释如下:

    • std::packaged_task 对象是异步 Provider,它在某一时刻通过调用被包装的任务来设置共享状态的值。
    • std::future 对象是一个异步返回对象,通过它可以获得共享状态的值,当然在必要的时候需要等待共享状态标志变为 ready.
    #include <iostream>     // std::cout
    #include <utility>      // std::move
    #include <future>       // std::packaged_task, std::future
    #include <thread>       // std::thread
    
    int main ()
    {
        std::packaged_task<int(int)> foo; // 默认构造函数.
    
        // 使用 lambda 表达式初始化一个 packaged_task 对象.
        std::packaged_task<int(int)> bar([](int x){return x*2;});
    
        foo = std::move(bar); // move-赋值操作,也是 C++11 中的新特性.
    
        // 获取与 packaged_task 共享状态相关联的 future 对象.
        std::future<int> ret = foo.get_future();
    
        std::thread(std::move(foo), 10).detach(); // 产生线程,调用被包装的任务.
    
        int value = ret.get(); // 等待任务完成并获取结果.
        std::cout << "The double of 10 is " << value << ".
    ";
    
    return 0;
    }
    View Code
    #include <iostream>
    #include <cmath>
    #include <thread>
    #include <future>
    #include <functional>
     
    // unique function to avoid disambiguating the std::pow overload set
    int f(int x, int y) { return std::pow(x,y); }
     
    void task_lambda()
    {
        std::packaged_task<int(int,int)> task([](int a, int b) {
            return std::pow(a, b); 
        });
        std::future<int> result = task.get_future();
     
        task(2, 9);
     
        std::cout << "task_lambda:	" << result.get() << '
    ';
    }
     
    void task_bind()
    {
        std::packaged_task<int()> task(std::bind(f, 2, 11));
        std::future<int> result = task.get_future();
     
        task();
     
        std::cout << "task_bind:	" << result.get() << '
    ';
    }
     
    void task_thread()
    {
        std::packaged_task<int(int,int)> task(f);
        std::future<int> result = task.get_future();
     
        std::thread task_td(std::move(task), 2, 10);
        task_td.join();
     
        std::cout << "task_thread:	" << result.get() << '
    ';
    }
     
    int main()
    {
        task_lambda();
        task_bind();
        task_thread();
    }
    
    /*
    输出结果
    task_lambda: 512
    task_bind:   2048
    task_thread: 1024
    */
    View Code

    std::remove_reference

    https://en.cppreference.com/w/cpp/types/remove_reference

    If the type T is a reference type, provides the member typedef type which is the type referred to by T. Otherwise typeis T.

    std::move和std::forward

    不错,可以仔细看看: https://www.jianshu.com/p/b90d1091a4ff

    https://www.cnblogs.com/boydfd/p/5182743.html

    std::function和std::bind

    https://www.jianshu.com/p/f191e88dcc80

    https://blog.csdn.net/zzhongcy/article/details/88018204

    std::function

    • std::function 是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
    • 定义格式:std::function<函数类型>。
    • std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。
    //不同类型可能具有相同的调用形式,如:
    // 普通函数
    int add(int a, int b){return a+b;} 
    
    // lambda表达式
    auto mod = [](int a, int b){ return a % b;}
    
    // 函数对象类
    struct divide{
        int operator()(int denominator, int divisor){
            return denominator/divisor;
        }
    };
    
    //上述三种可调用对象虽然类型不同,但是共享了一种调用形式:
    int(int ,int)
    
    //std::function就可以将上述类型保存起来,如下:
    std::function<int(int ,int)>  a = add; 
    std::function<int(int ,int)>  b = mod ; 
    std::function<int(int ,int)>  c = divide();
    View Code

    std::bind

    可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

    std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:

    • 将可调用对象和其参数绑定成一个防函数;
    • 只绑定部分参数,减少可调用对象传入的参数。

    绑定普通函数:

    double my_divide (double x, double y) {return x/y;}
    auto fn_half = std::bind (my_divide,_1,2);  
    std::cout << fn_half(10) << '
    ';                        // 5
    
    /*
    bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
    _1表示占位符,位于<functional>中,std::placeholders::_1;
    */
    View Code

    绑定成员函数:

    /*
    bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
    必须显示的指定&Foo::print_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::print_sum前添加&;
    使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;
    */
    struct Foo {
        void print_sum(int n1, int n2)
        {
            std::cout << n1+n2 << '
    ';
        }
        int data = 10;
    };
    int main() 
    {
        Foo foo;
        auto f = std::bind(&Foo::print_sum, &foo, 95, std::placeholders::_1);
        f(5); // 100
    }
    View Code

    std::rec和std::cref

    https://blog.csdn.net/lmb1612977696/article/details/81543802

    http://www.cnblogs.com/jiayayao/p/6527713.html

    C++本身有引用(&),为什么C++11又引入了std::ref?

      主要是考虑函数式编程(如std::bind)在使用时,是对参数直接拷贝,而不是引用。

    #include <functional>
    #include <iostream>
    
    void f(int& n1, int& n2, const int& n3)
    {
        std::cout << "In function: n1[" << n1 << "]    n2[" << n2 << "]    n3[" << n3 << "]" << std::endl;
        ++n1; // 增加存储于函数对象的 n1 副本
        ++n2; // 增加 main() 的 n2
        //++n3; // 编译错误
        std::cout << "In function end: n1[" << n1 << "]     n2[" << n2 << "]     n3[" << n3 << "]" << std::endl;
    }
    
    int main()
    {
        int n1 = 1, n2 = 1, n3 = 1;
        std::cout << "Before function: n1[" << n1 << "]     n2[" << n2 << "]     n3[" << n3 << "]" << std::endl;
        std::function<void()> bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
        bound_f();
        std::cout << "After function: n1[" << n1 << "]     n2[" << n2 << "]     n3[" << n3 << "]" << std::endl;
    }
    View Code

    std::result_of

    https://zh.cppreference.com/w/cpp/types/result_of

    它可以在编译的时候推导出一个函数表达式的返回值类型

    #include <type_traits>
    #include <iostream>
     
    struct S {
        double operator()(char, int&);
        float operator()(int) { return 1.0;}
    };
     
    template<class T>
    typename std::result_of<T(int)>::type f(T& t)
    {
        std::cout << "overload of f for callable T
    ";
        return t(0);
    }
     
    template<class T, class U>
    int f(U u)
    {
        std::cout << "overload of f for non-callable T
    ";
        return u;
    }
     
    int main()
    {
        // 以 char 和 int 参数调用 S 的结果是 double
        std::result_of<S(char, int&)>::type d = 3.14; // d 拥有 double 类型
        static_assert(std::is_same<decltype(d), double>::value, "");
     
        // 以 int 参数调用 S 的结果是 float
        std::result_of<S(int)>::type x = 3.14; // x 拥有 float 类型
        static_assert(std::is_same<decltype(x), float>::value, "");
     
        // result_of 能以指向成员函数的指针以如下方式使用
        struct C { double Func(char, int&); };
        std::result_of<decltype(&C::Func)(C, char, int&)>::type g = 3.14;
        static_assert(std::is_same<decltype(g), double>::value, "");
     
        f<C>(1); // C++11 中可能编译失败; C++14 中调用不可调用重载
    }
    View Code
  • 相关阅读:
    小程序上传多张图片
    小程序倒计时遇到的问题
    taro小程序展示富文本
    taro小程序地址选择组件
    构建基于Suricata+Splunk的IDS入侵检测系统
    SQL注入学习资料总结
    常见WAF绕过思路
    业务安全漏洞挖掘归纳总结
    细说验证码安全 —— 测试思路大梳理
    验证码安全那些事
  • 原文地址:https://www.cnblogs.com/gnivor/p/10418330.html
Copyright © 2020-2023  润新知