c++11中 std::ref() 和 引用 &

使用std::ref可以在模板传参的时候传入引用,否则无法传递
&是类型说明符, std::ref 是一个函数,返回 std::reference_wrapper(类似于指针)
用std::ref 是考虑到c++11中的函数式编程,如 std::bind.

C++11的设计者认为bind默认应该采用拷贝,如果使用者有需求,加上std::ref()即可。同理std::thread也是这样。

example:

#include 
#include 
 
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
}
 
int main()
{
    int n1 = 1, n2 = 2, n3 = 3;
    //bound_f 保存的是n1 = 1, n2 = 2, n3 = 3
    std::function<void()> bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
    n1 = 4;
    n2 = 5;
    n3 = 6;
    std::cout << "Before function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
    bound_f();//bound_f 保存的是n1 = 1, n2 = 2, n3 = 3, bound_f n1 是拷贝,依然输出1, n2 ref 输出改变后的5,n3 为6
    std::cout << "After function: " << n1 << ' ' << n2 << ' ' << n3 << '\n';
    // n2传入ref,  ++n2 为6, cref 为const ref, n3不能更改
}
Before function: 4 5 6
In function: 1 5 6
After function: 4 6 6

std::ref() and & 的区别

#include 
#include 
#include 
using namespace std;
int main()
{
    int x = 5;
    std::cout << boolalpha << is_same<int&, decltype(ref(x))>::value;
    return 0;
}

输出答案果然是false!那么如果std::ref()返回的不是对象的引用,返回的是什么?查一下手册可以发现:函数模板 ref 与 cref 是生成 std::reference_wrapper 类型对象的帮助函数,它们用模板实参推导确定结果的模板实参。所以std::ref()返回的实际上是一个reference_wrapper而不是T&,可以从一个指向不能拷贝的类型的对象的引用生成一个可拷贝的对象。 std::reference_wrapper 的实例是对象(它们可被复制或存储于容器),但它们能隐式转换成 T& ,故能以之为以引用接收底层类型的函数的参数。

修改代码后

#include 
#include 
#include 
using namespace std;
int main()
{
    int x = 5;
    std::cout << boolalpha << is_same<int&, decltype(ref(x).get())>::value;
    return 0;
}

变为true了。reference_wrapper与&并不一样,但是利用get()函数就是&类型。但是为什么在多线程那个例子中要使用std::ref()呢?

原因是,考虑了函数式编程(如std::bind)在使用时,是对参数直接拷贝,而不是引用。具体可以参照这一句话:std::reference_wrapper 用于按引用传递对象给 std::bind 或 std::thread 的构造函数

结论
std::ref只是尝试模拟引用传递,并不能真正变成引用,在非模板情况下,std::ref根本没法实现引用传递,只有模板自动推导类型时,ref能用包装类型reference_wrapper来代替原本会被识别的值类型,而reference_wrapper能隐式转换为被引用的值的引用类型,但是并不能被用作&类型。

而回到刚开始的那个多线程代码,thread的方法传递引用的时候,我们希望使用的是参数的引用,而不是浅拷贝,所以必须用ref来进行引用传递。

你可能感兴趣的:(cpp11,C++,c++,开发语言,visual,studio)