精华内容
下载资源
问答
  • C++11中std::async的使用
    千次阅读
    2020-02-01 14:33:23

    C++11中的std::async是个模板函数。std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员函数获取。一旦完成Fn的执行,共享状态将包含Fn返回的值并ready。

    std::async有两个版本:

    1.无需显示指定启动策略,自动选择,因此启动策略是不确定的,可能是std::launch::async,也可能是std::launch::deferred,或者是两者的任意组合,取决于它们的系统和特定库实现。

    2.允许调用者选择特定的启动策略。

    std::async的启动策略类型是个枚举类enum class launch,包括:

    1. std::launch::async:异步,启动一个新的线程调用Fn,该函数由新线程异步调用,并且将其返回值与共享状态的访问点同步。

    2. std::launch::deferred:延迟,在访问共享状态时该函数才被调用。对Fn的调用将推迟到返回的std::future的共享状态被访问时(使用std::future的wait或get函数)。

    参数Fn:可以为函数指针、成员指针、任何类型的可移动构造的函数对象(即类定义了operator()的对象)。Fn的返回值或异常存储在共享状态中以供异步的std::future对象检索。

    参数Args:传递给Fn调用的参数,它们的类型应是可移动构造的。

    返回值:当Fn执行结束时,共享状态的std::future对象准备就绪。std::future的成员函数get检索的值是Fn返回的值。当启动策略采用std::launch::async时,即使从不访问其共享状态,返回的std::future也会链接到被创建线程的末尾。在这种情况下,std::future的析构函数与Fn的返回同步。

    std::future介绍参考:https://blog.csdn.net/fengbingchun/article/details/104115489

    详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,部分作了调整,详细内容介绍可以参考对应的reference:

    #include "future.hpp"
    #include <iostream>
    #include <future>
    #include <chrono>
    #include <utility>
    #include <thread>
    #include <functional>
    #include <memory>
    #include <exception> 
    #include <numeric>
    #include <vector>
    #include <cmath>
    #include <string>
    #include <mutex>
    
    namespace future_ {
    
    ///
    // reference: http://www.cplusplus.com/reference/future/async/
    int test_async_1()
    {
    	auto is_prime = [](int x) {
    		std::cout << "Calculating. Please, wait...\n";
    		for (int i = 2; i < x; ++i) if (x%i == 0) return false;
    		return true;
    	};
    
    	// call is_prime(313222313) asynchronously:
    	std::future<bool> fut = std::async(is_prime, 313222313);
    
    	std::cout << "Checking whether 313222313 is prime.\n";
    	// ...
    
    	bool ret = fut.get(); // waits for is_prime to return
    	if (ret) std::cout << "It is prime!\n";
    	else std::cout << "It is not prime.\n";
    
    	return 0;
    }
    
    ///
    // reference: http://www.cplusplus.com/reference/future/launch/
    int test_async_2()
    {
    	auto print_ten = [](char c, int ms) {
    		for (int i = 0; i < 10; ++i) {
    			std::this_thread::sleep_for(std::chrono::milliseconds(ms));
    			std::cout << c;
    		}
    	};
    
    	std::cout << "with launch::async:\n";
    	std::future<void> foo = std::async(std::launch::async, print_ten, '*', 100);
    	std::future<void> bar = std::async(std::launch::async, print_ten, '@', 200);
    	// async "get" (wait for foo and bar to be ready):
    	foo.get(); // 注:注释掉此句,也会输出'*'
    	bar.get();
    	std::cout << "\n\n";
    
    	std::cout << "with launch::deferred:\n";
    	foo = std::async(std::launch::deferred, print_ten, '*', 100);
    	bar = std::async(std::launch::deferred, print_ten, '@', 200);
    	// deferred "get" (perform the actual calls):
    	foo.get(); // 注:注释掉此句,则不会输出'**********'
    	bar.get();
    	std::cout << '\n';
    
    	return 0;
    }
    
    ///
    // reference: https://en.cppreference.com/w/cpp/thread/async
    std::mutex m;
    
    struct X {
    	void foo(int i, const std::string& str) {
    		std::lock_guard<std::mutex> lk(m);
    		std::cout << str << ' ' << i << '\n';
    	}
    	void bar(const std::string& str) {
    		std::lock_guard<std::mutex> lk(m);
    		std::cout << str << '\n';
    	}
    	int operator()(int i) {
    		std::lock_guard<std::mutex> lk(m);
    		std::cout << i << '\n';
    		return i + 10;
    	}
    };
    
    template <typename RandomIt>
    int parallel_sum(RandomIt beg, RandomIt end)
    {
    	auto len = end - beg;
    	if (len < 1000)
    		return std::accumulate(beg, end, 0);
    
    	RandomIt mid = beg + len / 2;
    	auto handle = std::async(std::launch::async, parallel_sum<RandomIt>, mid, end);
    	int sum = parallel_sum(beg, mid);
    	return sum + handle.get();
    }
    
    int test_async_3()
    {
    	std::vector<int> v(10000, 1);
    	std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
    
    	X x;
    	// Calls (&x)->foo(42, "Hello") with default policy:
    	// may print "Hello 42" concurrently or defer execution
    	auto a1 = std::async(&X::foo, &x, 42, "Hello");
    	// Calls x.bar("world!") with deferred policy
    	// prints "world!" when a2.get() or a2.wait() is called
    	auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");
    	// Calls X()(43); with async policy
    	// prints "43" concurrently
    	auto a3 = std::async(std::launch::async, X(), 43);
    	a2.wait();                     // prints "world!"
    	std::cout << a3.get() << '\n'; // prints "53"
    
    	return 0;
    } // if a1 is not done at this point, destructor of a1 prints "Hello 42" here
    
    ///
    // reference: https://thispointer.com/c11-multithreading-part-9-stdasync-tutorial-example/
    int test_async_4()
    {
    	using namespace std::chrono;
    
    	auto fetchDataFromDB = [](std::string recvdData) {
    		// Make sure that function takes 5 seconds to complete
    		std::this_thread::sleep_for(seconds(5));
    		//Do stuff like creating DB Connection and fetching Data
    		return "DB_" + recvdData;
    	};
    
    	auto fetchDataFromFile = [](std::string recvdData) {
    		// Make sure that function takes 5 seconds to complete
    		std::this_thread::sleep_for(seconds(5));
    		//Do stuff like fetching Data File
    		return "File_" + recvdData;
    	};
    
    	// Get Start Time
    	system_clock::time_point start = system_clock::now();
    
    	std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");
    
    	//Fetch Data from File
    	std::string fileData = fetchDataFromFile("Data");
    
    	//Fetch Data from DB
    	// Will block till data is available in future<std::string> object.
    	std::string dbData = resultFromDB.get();
    
    	// Get End Time
    	auto end = system_clock::now();
    	auto diff = duration_cast <std::chrono::seconds> (end - start).count();
    	std::cout << "Total Time Taken = " << diff << " Seconds" << std::endl;
    
    	//Combine The Data
    	std::string data = dbData + " :: " + fileData;
    	//Printing the combined Data
    	std::cout << "Data = " << data << std::endl;
    
    	return 0;
    }
    
    } // namespace future_

    GitHubhttps://github.com/fengbingchun/Messy_Test

    更多相关内容
  • fatal error C1083: 无法打开包括文件:“stdint.h”: No such file or directory stdint.h是c99标准的头文件,vc不支持,所以肯定会提示“No such file or directory”的。 解决办法: 解压后会得到三个文件,把...
  • std::function和std::bind的使用

    千次阅读 2021-12-29 15:15:05
    1.std::function std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。 #...

    目录

    一、std::function

    1.包装普通的函数

    2.包装模板函数

    3.包装函数对象

    4.类模板

    5.普通类

    6.lambda表达式

    7.std::function的拷贝、移动


    一、std::function

    std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行

    1.包装普通的函数

    std::function<int(int)> callback;
    
    //1.普通的函数
    int func(int a){
        std::cout<< "func_ a :" << a << endl;
        return a;
    }
    
    
    int main()
    {
        //1.包装普通的函数
        callback = func;
        callback(10); 
    
        return 0;
    }

    2.包装模板函数

    template<class T>
    T func_template(T a)
    {
      std::cout<< "func_template a :" << a << endl;
      return a;
    }
    
    int main()
    {
        //2.包装模板函数 
        callback = func_template<double>;
        callback(20.0); //结果为2,这里callback是int类型的,所以都会转成int
        return 0;
    }

    3.包装函数对象

    //3.函数对象
    class FucntionClass
    {
    public:
        int operator()(int  a){
            std::cout<< "FucntionClass a :" << a << endl;
            return a;
        }
    };
    
    int main()
    {
        //3.包装函数对象
        callback = FucntionClass();
        callback(30);
        return 0;
    }

    4.类模板

    template<class T1>
    class FunctionClass_template
    {
    public:
        T1 operator()(T1 a){
            std::cout<< "template() a :" << a << endl;
            return a;
        }
    
        static T1 static_func(T1 a){
            std::cout<< "template func a :" << a << endl;
            return a;
        }
    
        T1 foo(T1 a){
             std::cout<< "template foo a :" << a << endl;
             return a;
        }
    };
    
    
    int main()
    {
        //4.类模板
        //4.1模板对象函数
        callback = FunctionClass_template<int>();
        callback(41);
        //4.2类模板static函数
        callback = FunctionClass_template<int>::static_func; //static 函数
        callback(42);
        //4.3类模板普通函数  
        FunctionClass_template<int> f_template;
        callback = std::bind(&FunctionClass_template<int>::foo,f_template,
        std::placeholders::_1);
        callback(43);
    
        return 0;
    }

    5.普通类

    #include <iostream>
    #include <functional>
    using namespace std;
    class MyClass
    {
    public:
        int operator()(int a){
            std::cout<< "MyClass() a :" << a << endl;
        }
        static int static_func(int a){
            std::cout<< "MyCLass  static_func a :" << a << endl;
            return a;
        }
        int foo(int a){
            std::cout<< "MyCLass  foo a :" << a << endl;
            return a;
        }
    };
    
    int main()
    {
        //5.普通类
        //5.1对象函数
        callback = MyClass();
        callback(51);
        //5.2类内静态函数
        callback = MyClass::static_func;
        callback(52);
        //5.3类内普通函数
        MyClass f_myclass;
        callback = std::bind(&MyClass::foo,f_myclass,std::placeholders::_1);
        callback(53);
    
        return 0;
    }

    6.lambda表达式

      auto f_lambda = [](int a){
            std::cout << "lambda   a:" << a << std::endl;
            return a;
        };
      callback = f_lambda;
      callback(61);

    7.std::function的拷贝、移动

    
        std::function<int(int)>callback_2 = callback;
        callback_2(71);
    
        std::function<int(int)>callback_3(callback);
        callback_3(72);
    
        std::function<int(int)>&& callback_4 = std::move(callback);
        callback_4(73);

      cpp文件如下:

    #include <iostream>
    #include <functional>
    
    using namespace std;
    
    std::function<int(int)> callback;
    
    //1.普通的函数
    int func(int a){
        std::cout<< "func_ a :" << a << endl;
        return a;
    }
    
    //2.类模板函数
    
    template<class T>
    T func_template(T a)
    {
      std::cout<< "func_template a :" << a << endl;
      return a;
    }
    
    //3.函数对象
    class FucntionClass
    {
    public:
        int operator()(int  a){
            std::cout<< "FucntionClass a :" << a << endl;
            return a;
        }
    };
    
    //4.模板对象函数
    template<class T1>
    class FunctionClass_template
    {
    public:
        T1 operator()(T1 a){
            std::cout<< "template() a :" << a << endl;
            return a;
        }
    
        static T1 static_func(T1 a){
            std::cout<< "template func a :" << a << endl;
            return a;
        }
    
        T1 foo(T1 a){
             std::cout<< "template foo a :" << a << endl;
             return a;
        }
    };
    
    class MyClass
    {
    public:
        int operator()(int a){
            std::cout<< "MyClass() a :" << a << endl;
        }
        static int static_func(int a){
            std::cout<< "MyCLass  static_func a :" << a << endl;
            return a;
        }
        int foo(int a){
            std::cout<< "MyCLass  foo a :" << a << endl;
            return a;
        }
    };
    
    template <typename T>
    class foo4{
    public:
        T foo(T a){
            return a * 6;
        }
    };
    
    int main()
    {
        //一般出现问题都是callback的参数or返回值类型和自定义的不匹配所致
      
        //1.包装普通的函数
        callback = func;
        callback(10); 
    
        //2.包装模板函数 
        callback = func_template<double>;
        callback(20.0); //结果为2,这里callback是int类型的,所以都会转成int
    
        //3.包装函数对象
        callback = FucntionClass();
        callback(30);
    
       
        //4.类模板
        //4.1模板对象函数
        callback = FunctionClass_template<int>();
        callback(41);
        //4.2类模板static函数
        callback = FunctionClass_template<int>::static_func; //static 函数
        callback(42);
        //4.3类模板普通函数  
        FunctionClass_template<int> f_template;
        callback = std::bind(&FunctionClass_template<int>::foo,f_template, std::placeholders::_1);
        callback(43);
    
        //5.普通类
        //5.1对象函数
        callback = MyClass();
        callback(51);
        //5.2类内静态函数
        callback = MyClass::static_func;
        callback(52);
        //5.3类内普通函数
        MyClass f_myclass;
        callback = std::bind(&MyClass::foo,f_myclass,std::placeholders::_1);
        callback(53);
    
        //6.lambda表达式
    
        auto f_lambda = [](int a){
            std::cout << "lambda   a:" << a << std::endl;
            return a;
        };
    
        callback = f_lambda;
        callback(61);
    
        //7.std::function的拷贝、移动
    
        std::cout << " ------------ " << std::endl;
        std::function<int(int)>callback_2 = callback;
        callback_2(71);
    
        std::function<int(int)>callback_3(callback);
        callback_3(72);
    
        std::function<int(int)>&& callback_4 = std::move(callback);
        callback_4(73);
        
        return 0;
    }

    2.std::bind

    bind相当于一个适配器模板类

    上图中的callfunc1是我们已经实现的函数,newCall是通过std::bind重新包装的函数。

    bind的函数原型:
    auto newfunc = bind(func, arg_list);
    该形式表达的意思是:当调用newfunc时,会调用func,并传给它arg_list中的参数。
    
    实战中
    auto newCall = std::bind(callfunc1,std::placeholders::_1,20);
    
    newCall可以只接收一个参数,调用newCall后会调用callfunc1,比如现在执行了
    newCall(99);
    这时回调给callfunc1的就是 callfunc1(99,20);
    
    2.类内函数,要将this传参哦
    
    class A {
    public:
        void fun(int k,int m) {
            cout << " k="<< k << ", m = " << m <<endl;
        }
    };
    
    A a;
    auto newClassCall = std::bind(&A::fun,&a,std::placeholders::_1,11);
    newClassCall(15);

    展开全文
  • stdint.h头文件

    千次下载 热门讨论 2013-07-13 16:47:50
    很多项目经常使用的两个头文件inttypes.h stdint.h,否则会报错。网上很多资料,但基本上不可用。这两个文件,我在自己的项目中运行良好。
  • C++11的std::ref、std::cref源码解析

    万次阅读 多人点赞 2021-05-09 11:13:21
    C++11的std::ref、std::cref源码解析1、源码准备2、std::ref和std::cref的作用3、std::ref相关源码解析3.1、std::ref解析3.1、std::reference_wrapper解析3.3、std::remove_cv解析3.4、std::_Reference_wrapper_base...

    1、源码准备

    本文是基于gcc-4.9.0的源代码进行分析,std::ref和std::cref是C++11才加入标准的,所以低版本的gcc源码是没有这两个的,建议选择4.9.0或更新的版本去学习,不同版本的gcc源码差异应该不小,但是原理和设计思想的一样的,下面给出源码下载地址
    http://ftp.gnu.org/gnu/gcc

    2、std::ref和std::cref的作用

    C++本身就有引用(&),那为什么C++11又引入了std::ref(或者std::cref)呢?
    答案很简单,这主要是考虑函数式编程(如std::bind)在使用时,是对参数直接拷贝,而不是引用。下面举一个简单的例子大家就明白了。

    #include <functional>
    #include <iostream>
     
    void fun(int& n1, int& n2, const int& n3)
    {
        std::cout << "In function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
        ++n1; // increments the copy of n1 stored in the function object
        ++n2; // increments the main()'s n2
        // ++n3; // compile error
        std::cout << "In function end: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
    }
     
    int main()
    {
        int n1 = 1, n2 = 1, n3 = 1;
        std::function<void()> fff = std::bind(f, n1, std::ref(n2), std::cref(n3));
        std::cout << "Before function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
        fff();
        std::cout << "After function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
    }
    

    运行结果:

    Before function: 1 1 1
    In function: 1 1 1
    In function end: 2 2 1
    After function: 1 2 1
    

    从上面的例子中可以看到,执行完fff,n1的值仍然是1,n2的值已经改变,这说明std::bind使用的是参数的拷贝而不是引用,这也就是为什么C++11要引入std::refstd::cref的原因了,接下来分析std::ref的实现(std::cref不作分析,因为std::crefstd::ref唯一的差别只是引用变成了const而已)

    3、std::ref相关源码解析

    3.1、std::ref解析

    std::ref位于libstdc++-v3\include\std\functional

    template<typename _Tp>
    inline reference_wrapper<_Tp> ref(_Tp& __t) noexcept
    { return reference_wrapper<_Tp>(__t); }
    
    template<typename _Tp>
    void ref(const _Tp&&) = delete;
    
    template<typename _Tp>
    inline reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t) noexcept
    { return ref(__t.get()); }
    

    从源代码中可以看出以下几点信息:

    1. std::ref是一个模板函数,返回值是模板类std::reference_wrapper
    2. 从第二个函数可以看到,std::ref不允许传递右值引用参数,即无法包装右值引用传递的值
    3. std::ref的传入参数可以是一个普通的引用,也可以是另外一个std::reference_wrapper对象,接下来分析std::reference_wrapper的实现

    3.1、std::reference_wrapper解析

    std::reference_wrapper位于libstdc++-v3\include\std\functional

    template<typename _Tp>
    class reference_wrapper : public _Reference_wrapper_base<typename remove_cv<_Tp>::type>
    {
        _Tp* _M_data;
    
    public:
        typedef _Tp type;
    
        reference_wrapper(_Tp& __indata) noexcept
            :_M_data(std::__addressof(__indata))
        {
        }
    
        reference_wrapper(_Tp&&) = delete;
    
        reference_wrapper(const reference_wrapper<_Tp>& __inref) noexcept
            :_M_data(__inref._M_data)
        {
        }
    
        reference_wrapper& operator=(const reference_wrapper<_Tp>& __inref) noexcept
        {
            _M_data = __inref._M_data;
            return *this;
        }
    
        operator _Tp&() const noexcept
        { return this->get(); }
    
        _Tp& get() const noexcept
        { return *_M_data; }
    
        template<typename... _Args>
        typename result_of<_Tp&(_Args&&...)>::type
        operator()(_Args&&... __args) const
        {
            return __invoke(get(), std::forward<_Args>(__args)...);
        }
    };
    

    从源代码中可以看出以下几点信息:

    1. 该类继承于std::_Reference_wrapper_base
    2. 有一个类成员_M_data,类型为所引用类型的指针
    3. 第一个构造函数通过调用std::__addressof函数,获得了指向引用参数的指针,并赋值给了_M_data(这也是为什么不支持右值引用的原因,因为取不到对应的地址),至于这里为什么要使用std::__addressof大家可以看一下这篇文章《C++11的std::addressof源码解析》,里面有详细介绍,这里就不重复叙述了
    4. 拷贝构造函数和赋值函数就只是简单地将_M_data的值进行传递而已,没有什么特殊操作
    5. 其余方法就是为了让std::reference_wrapper展现出和普通的引用一样的效果而进行的运算符重载啥的,这里就不赘述了,实现比较简单,大家可以自己看一看具体的代码

    3.3、std::remove_cv解析

    std::remove_cv位于libstdc++-v3\include\std\type_traits

    分析std::_Reference_wrapper_base之前先看一下std::remove_cv的实现:
    其实从std::remove_cv存在于type_traits文件这一点就可以大致推断出,std::remove_cv使用了模板元技术,模板元的主要思想为:利用模板特化机制实现编译期条件选择结构,利用递归模板实现编译期循环结构,模板元程序则由编译器在编译器解释运行,但是其也有明显的优缺点,优点是运行时速度极快,缺点是程序很难看懂,容易劝退初学者,这里不对其做深入分析,知道是这样一个东西就行,有兴趣的可以去查阅专业的C++书籍去了解其中的奥秘
    源代码如下,作用是将模板_Tpconstvoaltile属性分离,这样的话使用::value就可以得到没有const、volatile的类型了

    /// remove_const
    template<typename _Tp>
    struct remove_const
    { typedef _Tp    type; };
    
    template<typename _Tp>
    struct remove_const<_Tp const>
    { typedef _Tp    type; };
    
    /// remove_volatile
    template<typename _Tp>
    struct remove_volatile
    { typedef _Tp    type; };
    
    template<typename _Tp>
    struct remove_volatile<_Tp volatile>
    { typedef _Tp    type; };
    
    /// remove_cv
    template<typename _Tp>
    struct remove_cv
    {
      typedef typename
      remove_const<typename remove_volatile<_Tp>::type>::type    type;
    };
    

    3.4、std::_Reference_wrapper_base解析

    std::_Reference_wrapper_base位于libstdc++-v3\include\std\functional

    template<typename _Tp>
    struct _Reference_wrapper_base
        :_Reference_wrapper_base_impl<
         __has_argument_type<_Tp>::value,
         __has_first_argument_type<_Tp>::value
         && __has_second_argument_type<_Tp>::value,
         _Tp>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res(_T1)> : unary_function<_T1, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res(_T1) const> : unary_function<_T1, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res(_T1) volatile> : unary_function<_T1, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res(_T1) const volatile> : unary_function<_T1, _Res>
    {};
    
    // - a function type (binary)
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res(_T1, _T2)> : binary_function<_T1, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res(_T1, _T2) const> : binary_function<_T1, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> : binary_function<_T1, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> : binary_function<_T1, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res(*)(_T1)> : unary_function<_T1, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res(*)(_T1, _T2)> : binary_function<_T1, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res (_T1::*)()> : unary_function<_T1*, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res (_T1::*)(_T2)> : binary_function<_T1*, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res (_T1::*)() const> : unary_function<const _T1*, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const> : binary_function<const _T1*, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res (_T1::*)() volatile> : unary_function<volatile _T1*, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res (_T1::*)(_T2) volatile> : binary_function<volatile _T1*, _T2, _Res>
    {};
    
    template<typename _Res, typename _T1>
    struct _Reference_wrapper_base<_Res (_T1::*)() const volatile> : unary_function<const volatile _T1*, _Res>
    {};
    
    template<typename _Res, typename _T1, typename _T2>
    struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const volatile> : binary_function<const volatile _T1*, _T2, _Res>
    {};
    

    从代码中可以看出,std::_Reference_wrapper_base继承于std::unary_function或者std::binary_function,在实际编程中对std::reference_wrapper的影响不大,除非引用的是一个函数对象,所以在这里就不分析它的具体作用了,大家自己去查一下unary_functionbinary_function是啥东西就行了

    4、总结

    std::refstd::cref在函数式编程中的作用是非常大的,C++标准库中多次使用到了它们。而std::refstd::cref事实上是模板函数,返回值是一个std::reference_wrapper对象,而std::reference_wrapper虽然是一个对象,可是他却能展现出和普通引用类似的效果,这点和前一篇文章讲的智能指针如出一辙(事实上标准库大多是这样设计的,这也是运算符重载存在的一个重要意义)。当我们在函数式编程(如std::bind)中需要对参数进行引用传递时,只需要使用用std::refstd::cref修饰该引用即可。

    最后,如果大家觉得本文写得好的话麻烦点赞收藏关注一下谢谢,也可以关注该专栏,以后会有更多优质文章输出的。

    展开全文
  • C++11中std::future的使用

    万次阅读 多人点赞 2020-01-30 15:28:45
    C++11中的std::future是一个模板类。std::future提供了一种用于访问异步操作结果的机制。std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::shared_future相反)( std::future references shared ...

    C++11中的std::future是一个模板类。std::future提供了一种用于访问异步操作结果的机制std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::shared_future相反)( std::future references shared state that is not shared with any other asynchronous return objects (as opposed to std::shared_future))。一个future是一个对象,它可以从某个提供者的对象或函数中检索值,如果在不同的线程中,则它可以正确地同步此访问(A future is an object that can retrieve a value from some provider object or function, properly synchronizing this access if in different threads)。

    有效的future是与共享状态(shared state)关联的future对象,可以通过调用以下函数(provider)来构造future对象:std::async、std::promise::get_future、std::packaged_task::get_future。future对象仅在它们是有效时才有用。

    std::aysnc介绍参考:https://blog.csdn.net/fengbingchun/article/details/104133494

    std::promise介绍参考:https://blog.csdn.net/fengbingchun/article/details/104124174

    std::packaged_task介绍参考:https://blog.csdn.net/fengbingchun/article/details/104127352

    模板类std::future成员函数包括:

    1. 构造函数:(1).不带参数的默认构造函数,此对象没有共享状态,因此它是无效的,但是可以通过移动赋值的方式将一个有效的future值赋值给它;(2).禁用拷贝构造;(3).支持移动构造。

    2. 析构函数:销毁future对象,它是异常安全的。

    3. get函数:(1).当共享状态就绪时,返回存储在共享状态中的值(或抛出异常)。(2).如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将取消阻塞并返回(或抛出)释放其共享状态,这使得future对象不再有效,因此对于每一个future共享状态,该函数最多应被调用一次。(4).std::future<void>::get()不返回任何值,但仍等待共享状态就绪并释放它。(5).共享状态是作为原子操作(atomic operation)被访问。

    4. operator=:(1).禁用拷贝赋值。(2).支持移动赋值:如果在调用之前,此对象是有效的(即它已经访问共享状态),则将其与先前已关联的共享状态解除关联。如果它是与先前共享状态关联的唯一对象,则先前的共享状态也会被销毁。

    5. share函数:获取共享的future,返回一个std::shared_future对象,该对象获取future对象的共享状态。future对象将不再有效。

    6. valid函数:检查共享状态的有效性,返回当前的future对象是否与共享状态关联。一旦调用了std::future::get()函数,再调用此函数将返回false。

    7. wait函数:(1).等待共享状态就绪。(2).如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将取消阻塞并void返回。

    8. wait_for函数:(1).等待共享状态在指定的时间内(time span)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到设置的时间。(3).此函数的返回值类型为枚举类future_status。此枚举类有三种label:ready:共享状态已就绪;timeout:在指定的时间内未就绪;deferred:共享状态包含了一个延迟函数(deferred function)。

    9. wait_until函数:(1). 等待共享状态在指定的时间点(time point)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到指定的时间点。(3).此函数的返回值类型为枚举类future_status。

    详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,部分作了调整,详细内容介绍可以参考对应的reference:

    #include "future.hpp"
    #include <iostream>
    #include <future>
    #include <chrono>
    #include <utility>
    #include <thread>
    
    namespace future_ {
    
    ///
    // reference: http://www.cplusplus.com/reference/future/future/
    int test_future_1()
    {
    { // constructor/get/operator=
    	auto get_value = []() { return 10; };
    	std::future<int> foo; // default-constructed
    	std::future<int> bar = std::async(get_value); // move-constructed
    
    	int x = bar.get();
    	std::cout << "value: " << x << '\n'; // 10
    
    	//int x2 = bar.get(); // crash, 对于每个future的共享状态,get函数最多仅被调用一次
    	//std::cout << "value: " << x2 << '\n';
    
    	std::future<int> foo2(std::async(get_value));
    	std::cout << "value: " << foo2.get() << '\n'; // 10
    }
    
    { // share
    	std::future<int> fut = std::async([]() { return 10; });
    	std::shared_future<int> shfut = fut.share();
    
    	//std::cout << "value: " << fut.get() << '\n'; // crash, 执行完fut.share()后,fut对象将变得无效
    	std::cout << "fut valid: " << fut.valid() << '\n';// 0
    
    	// shared futures can be accessed multiple times:
    	std::cout << "value: " << shfut.get() << '\n'; // 10
    	std::cout << "its double: " << shfut.get() * 2 << '\n'; // 20, 对于std::shared_future对象,get函数可以被多次访问
    }
    
    { // valid
    	std::future<int> foo, bar;
    	foo = std::async([]() { return 10; });
    	bar = std::move(foo);
    
    	if (foo.valid()) std::cout << "foo's value: " << foo.get() << '\n';
    	else std::cout << "foo is not valid\n"; // foo is not valid
    
    	if (bar.valid()) std::cout << "bar's value: " << bar.get() << '\n'; // 10
    	else std::cout << "bar is not valid\n";
    }
    
    { // wait
    	auto is_prime = [](int x) {
    		for (int i = 2; i < x; ++i) if (x%i == 0) return false;
    		return true;
    	};
    
    	// call function asynchronously:
    	std::future<bool> fut = std::async(is_prime, 194232491);
    
    	std::cout << "checking...\n";
    	fut.wait();
    
    	std::cout << "\n194232491 ";
    	if (fut.get()) // guaranteed to be ready (and not block) after wait returns
    		std::cout << "is prime.\n";
    	else
    		std::cout << "is not prime.\n";
    }
    
    { // wait_for
    	auto is_prime = [](int x) {
    		for (int i = 2; i < x; ++i) if (x%i == 0) return false;
    		return true;
    	};
    
    	// call function asynchronously:
    	std::future<bool> fut = std::async(is_prime, 700020007);
    
    	// do something while waiting for function to set future:
    	std::cout << "checking, please wait";
    	std::chrono::milliseconds span(100);
    	while (fut.wait_for(span) == std::future_status::timeout) // 可能多次调用std::future::wait_for函数
    		std::cout << '.';
    
    	bool x = fut.get(); // retrieve return value
    	std::cout << "\n700020007 " << (x ? "is" : "is not") << " prime.\n";
    }
    
    	return 0;
    }
    
    ///
    // reference: https://en.cppreference.com/w/cpp/thread/future
    int test_future_2()
    {
    	// future from a packaged_task
    	std::packaged_task<int()> task([] { return 7; }); // wrap the function
    	std::future<int> f1 = task.get_future();  // get a future
    	std::thread t(std::move(task)); // launch on a thread
    
    	// future from an async()
    	std::future<int> f2 = std::async(std::launch::async, [] { return 8; });
    
    #ifdef _MSC_VER
    	// future from a promise
    	std::promise<int> p;
    	std::future<int> f3 = p.get_future();
    	std::thread([&p] { p.set_value_at_thread_exit(9); }).detach(); // gcc 4.9 don't support this function
    #endif
    
    	std::cout << "Waiting..." << std::flush;
    	f1.wait();
    	f2.wait();
    #ifdef _MSC_VER
    	f3.wait();
    #endif
    	std::cout << "Done!\nResults are: " << f1.get() << ' ' << f2.get() << ' '
    #ifdef _MSC_VER
    		<< f3.get()
    #endif
    		<< '\n';
    	t.join();
    
    	return 0;
    }
    
    ///
    // reference: https://thispointer.com/c11-multithreading-part-8-stdfuture-stdpromise-and-returning-values-from-thread/
    void initiazer(std::promise<int> * promObj)
    {
    	std::cout << "Inside Thread" << std::endl;
    	promObj->set_value(35);
    }
    
    int test_future_3()
    {
    	std::promise<int> promiseObj;
    	std::future<int> futureObj = promiseObj.get_future();
    	std::thread th(initiazer, &promiseObj);
    	std::cout << "value: " << futureObj.get() << std::endl;
    	th.join();
    
    	// If std::promise object is destroyed before setting the value the calling get() function on associated std::future object will throw exception.
    	// A part from this, if you want your thread to return multiple values at different point of time then
    	// just pass multiple std::promise objects in thread and fetch multiple return values from thier associated multiple std::future objects.
    
    	return 0;
    }
    
    } // namespace future_

    GitHubhttps://github.com/fengbingchun/Messy_Test

    展开全文
  • C++11中std::promise的使用

    千次阅读 2020-01-31 14:46:11
    C++11中的std::promise是个模板类。一个std::promise对象可以存储由future对象(可能在另一个线程中)检索的T类型的值或派生自std::exception的异常,并提供一个同步点。 在构造std::promise对象时,该对象与新的共享...
  • C++11中std::packaged_task的使用

    千次阅读 2020-01-31 19:53:45
    C++11中的std::packaged_task是个模板类。std::packaged_task包装任何可调用目标(函数、lambda表达式、bind表达式、函数对象)以便它可以被异步调用。它的返回值或抛出的异常被存储于能通过std::future对象访问的共享...
  • C++11中std::shared_future的使用

    千次阅读 2020-01-30 20:58:29
    C++11中的std::shared_future是个模板类。与std::future类似,std::shared_future提供了一种访问异步操作结果的机制;不同于std::future,std::shared_future允许多个线程等待同一个共享状态;不同于std::future仅...
  • C++11 多线程(std::thread)详解

    万次阅读 多人点赞 2021-07-17 19:40:26
    进程与线程的区别C++11的std::threadstd::thread常用成员函数构造&析构函数常用成员函数举个栗子例一:thread的基本使用例二:thread执行有参数的函数例三:thread执行带有引用参数的函数注意事项(剩下的内容还...
  • C++文件读写操作std::ofstream和std::ofstream
  • C++ STL 为std::unordered_set提供自定义哈希函数 所有哈希表都使用一个哈希函数,该函数将放入容器的元素的值映射到特定的存储桶。目标两个是相等的值始终生成相同的存储桶索引,而对于不同的值,理想情况下应处理...
  • std函数

    千次阅读 2021-05-21 00:37:36
    (Andrew Ng《机器学习》中ex1,线性回归)std函数是用来计算标准偏差的一个函数,由于其有不同的参数,我们就用下面的例子进行介绍:A =1 2 31 1 1标准差的两种计算公式如下:std(A):std(A)函数求解的是最常见的标准...
  • C++11的右值引用、移动语义(std::move)和完美转发(std::forward)详解1、源码准备2、C++11右值引用概念2.1、左值和右值2.2、右值引用3、C++11的移动语义(std::move)和完美转发(std::forward)3.1、移动语义...
  • C++ STL标准库:std::vector 使用详解

    万次阅读 多人点赞 2020-12-15 22:02:12
    文章目录1. 简介2. 使用示例3. 构造、析构、赋值3.1 std::... Iterators 迭代器4.1 std::vector::begin4.2 std::vector::end4.3 std::vector::rbegin4.4 std::vector::rend4.5 std::vector::cbegin (C++11)4.6 std
  • C++17之std::variant

    万次阅读 2019-09-05 21:55:18
    由于这个原因,您不能有non-trivial的成员,比如std::string(从c++ 11起, union原则上可以有non-trivial的成员,但是必须实现特殊的成员函数,比如复制构造函数和析构函数,因为只有通过代码逻辑才...
  • C++17之std::optional

    万次阅读 多人点赞 2019-09-05 21:45:03
    在编程中,我们经常遇到这样的情况:我们可能返回/传递/使用某种类型的对象。也就是说,我们可以有某个类型的值,也可以没有任何值。...std::optional<>以一种类型安全的方式提供了这样的对象。...
  • C++11中的std::bind

    万次阅读 多人点赞 2019-08-29 16:09:59
    看看这段代码 这几天学习Cocos2d-x,看到了以下的一段代码: // new callbacks based on C++11 #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__tar...
  • 在C++ 11之前,官方并没有支持线程库。在Linux下完成多线程编程时,多数情况下是使用#include <pthread.h>的函数。C++ 11通过标准库引入了对thread类的...std::thread 定义于头文件<thread> classt...
  • 1 小时转换为分钟/秒/毫秒/微秒 #include <iostream> #include <string> #include <... std::chrono::minutes minutes_time = std::chrono::duration_cast<std::chrono::minutes>(h
  • C++11的std::mem_fn源码解析

    千次阅读 多人点赞 2021-05-19 21:55:47
    C++11的std::mem_fn源码解析1、源码准备2、通过一个简单的例子来了解std::mem_fn的作用3、std::mem_fn源码解析3.1、std::mem_fn解析3.2、std::_Mem_fn解析3.3、在代码中正确使用std::_Mem_fn4、总结 1、源码准备 ...
  • 在公司说的项目代码中看到了std::function、std::bind、std::placeholders三个C++11的特性,通过了解之后,发现还是挺有用的,在这里记录下吧。似乎这三个特性一般都是一起使用的,所以也一起讲了。 三个特性都在...
  • C++ - std::shared_ptr::get

    万次阅读 2020-07-05 23:46:09
    C++ - std::shared_ptr::get public member function - 公开成员函数 Defined in header <memory> - 定义于头文件 <memory> 1. std::shared_ptr::get element_type* get() const noexcept; Get pointer...
  • std::list 简介1 std::list 定义对象2 std::list添加元素3 std::list删除元素4 std::list容器容量5 std::list迭代器6 std::list判断是否为空7 std::list元素的存取和访问8 std::list元素重置9 std::list 交换两个...
  • C++11中提供了std::mutex互斥量,共包含四种类型: std::mutex:最基本的mutex类。 std::recursive_mutex:递归mutex类,能多次锁定而不死锁。 std::time_mutex:定时mutex类,可以锁定一定的时间。 std::...
  • 在C++11中,提供了std::function和std::bind两个方法来对可回调对象进行统一和封装。 可调用对象 C++中有如下几种可调用对象:函数、函数指针、lambda表达式、bind对象、函数对象。其中lambda表达式和bind对象是C++...
  • C++17之std::any

    万次阅读 多人点赞 2019-09-05 22:00:10
    std: any是一种值类型,它能够更改其类型,同时仍然具有类型安全性。也就是说,对象可以保存任意类型的值,但是它们知道当前保存的值是哪种类型。在声明此类型的对象时,不需要指定可能的类型。 诀窍在于,对象...
  • 1 std::bind template <class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args); template <class Ret, class Fn, class... Args> /* unspecified */ bind (Fn&...
  • C++17之std::byte

    千次阅读 2019-09-05 22:01:33
    在c++ 17引入了 一种std::byte类型,它确实表示内存元素的“nature”类型字节。与char或int类型的关键区别在于,它不是字符类型且非算术类型。 byte 只是位的汇集,而且只对它定义逐位运算符。即唯一支持的“计算”...
  • C++17之std::visit

    千次阅读 2019-09-05 21:58:17
    std::cout << std::get<std::string>(var3) << std::endl; return 0; } 结果如下: 注意,对象操作符应该为const函数,因为它们是无状态的(它们不改变它们的行为,只改变传递的值,即不改变成员变量的值...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,739,242
精华内容 1,495,696
关键字:

std

友情链接: gyro_invensense.zip