std::ref和std::cref使用

为什么C++11引入了std::ref?

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <functional>
    #include <iostream>

    void f(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
    }

    int main()
    {
    int n1 = 1, n2 = 2, n3 = 3;
    std::function<void()> bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
    n1 = 10;
    n2 = 11;
    n3 = 12;
    std::cout << "Before function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
    bound_f();
    std::cout << "After function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
    }
  • output

1
2
3
4
Output:
Before function: 10 11 12
In function: 1 11 12
After function: 10 12 12
  • 上述代码在执行std::bind后,在函数f()中n1的值仍然是1,n2和n3改成了修改的值。说明std::bind使用的是参数的拷贝而不是引用。具体为什么std::bind不使用引用,可能确实有一些需求,使得C++11的设计者认为默认应该采用拷贝,如果使用者有需求,加上std::ref即可。

创建线程的时候也会用到!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <chrono>
#include <future>
#include <iostream>
#include <thread>

struct _data {
int32_t value;
};

_data data = {0};

int main() {
std::promise<_data> data_promise; //创建一个承诺
std::future<_data> data_future =
data_promise.get_future(); //得到这个承诺封装好的期望

// prepare func

auto prepare_data_func = std::bind(
[](std::promise<_data> &data_promise) {
std::this_thread::sleep_for(std::chrono::seconds(2)); //模拟生产过程
data_promise.set_value({221}); //通过set_value()反馈结果
},
std::ref(data_promise));

// process func
auto process_data_func = std::bind(
[](std::future<_data> &data_future) {
std::cout << data_future.get().value << std::endl; //通过get()获取结果
},
std::ref(data_future));

std::thread prepare_data_thread(prepare_data_func);
std::thread process_data_thread(process_data_func);
prepare_data_thread.join();
process_data_thread.join();

std::cout << "--- pause ---" << std::endl;
return 0;
}