需要的變量(variable)容器(container)只需要初始化一次,以容器(containter)為例子,可能只是需要向其中注入一次元素. C++11開始標准庫提供了std::call_once()和std::once_flag的組合可以幫助我們做到這一點. 在多線程編程中,有一個常見的情景是某個任務僅僅須要運行一次。
//Demo1
1 #include <iostream> 2 #include <thread> 3 #include <mutex> 4 #include <vector> 5 6 std::vector<int> vec; 7 std::mutex mutex; 8 std::once_flag flag; 9 10 static int val = 0; 11 12 void initialized_vec(std::vector<int>& vec) 13 { 14 for (int i = 0; i < 10; ++i) { 15 vec.push_back(val++); 16 } 17 } 18 19 void print_vec() 20 { 21 std::call_once(flag, initialized_vec, vec); 22 std::lock_guard<std::mutex> auto_lock(mutex); 23 for (const int& number : vec) { 24 std::cout << number << " "; 25 } 26 std::cout << std::endl; 27 } 28 29 int main() 30 { 31 std::thread threads[5]; 32 for (int i = 0; i < 5; ++i) { 33 threads[i] = std::thread(print_vec); 34 } 35 36 for (std::thread& ref_thread : threads) { 37 ref_thread.join(); 38 } 39 40 return 0; 41 }
//Demo2
1 #include <iostream> 2 #include <thread> 3 #include <mutex> 4 5 #include "Singleton.h" 6 7 8 void function(int& number) 9 { 10 number = 20; 11 } 12 13 int main() 14 { 15 int number{ 0 }; 16 std::once_flag onceFlag; 17 18 std::call_once(onceFlag, function, number); 19 std::cout << number << std::endl; //20! ref number 20 21 return 0; 22 }
其中頭文件#include<mutex>即可使用。下面為頭文件中的聲明。能夠看到once_flag是不同意改動的。拷貝構造函數和operator=函數都聲明為delete,這樣防止程序猿亂用。另外,call_once也是非常easy的。僅僅要傳進一個once_flag。回調函數,和參數列表就能夠了。
1 struct once_flag 2 { 3 constexpr once_flag() noexcept; 4 once_flag(const once_flag&) = delete; 5 once_flag& operator=(const once_flag&) = delete; 6 }; 7 template<class Callable, class ...Args> 8 void call_once(once_flag& flag, Callable&& func, Args&&... args); 9 10 } // std