C++ ref和引用(&)

1.简介:

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

  • bind

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

  • thread

其中代表的例子是thread
比如thread的方法传递引用的时候,必须外层用ref来进行引用传递,否则就是浅拷贝。

2.使用
class TestRef
{
public:
	TestRef():i(0)//默认构造函数 
	{
		cout << "TestRef默认构造函数" << this << endl;
	} 	
	TestRef(const TestRef&testR) :i(0) //拷贝构造函数
	{
		cout << "TestRef拷贝构造函数" << this << endl;
	}
	~TestRef()//析构函数
	{
		cout << "TestRef析构函数" << this << endl;
	}
	mutable int i ;
};


class TestRef1
{
public:
	TestRef1() :i(0)//默认构造函数 
	{
		cout << "TestRef1默认构造函数" << this << endl;
	}
	TestRef1(const TestRef1& testR) :i(0) //拷贝构造函数
	{
		cout << "TestRef1拷贝构造函数" << this << endl;
	}
	~TestRef1()//析构函数
	{
		cout << "TestRef1析构函数" << this << endl;
	}
	mutable int i=0;
};


void funs(const TestRef&test1, const TestRef1&test2)
{
	cout << "function " << "test1:" << &test1 <<" "<< test1.i << endl;
	cout << "function " << "test2:" << &test2 <<" "<< test2.i << endl;
	test1.i++;
	test2.i++;
}
void testFunction()
{
	TestRef t1;
	TestRef1 t2;
	cout << "testFunction " << "t1:" << &t1 << " " << t1.i << " t2:" << " " << &t2 << " " << t2.i << endl;
	funs(t1,t2);
	cout << "testFunction " << "t1:" << &t1 <<" "<< t1.i << " t2:" <<" " << &t2 << " " << t2.i <<endl;
}
int main()
{
	testFunction();
}

C++ ref和引用(&)_第1张图片
直接用引用 &是可以改变i的值的,那么为什么还要用ref呢?

再上一段代码。


void testFunction()
{
	TestRef t1;
	TestRef1 t2;
	function<void()> f1 = bind(funs, t1, ref(t2));
	f1();
	cout << "testFunction " << "t1:" << &t1 << " " << t1.i << " t2:" << " " << &t2 << " " << t2.i << endl;
}

C++ ref和引用(&)_第2张图片

通过输出的结果可以看到t1没有改变其中的i值,使用了ref的t2是直接把地址传给了test2,所以改变了其中i的值。
但是通过结果可以看出来,test1是拷贝的对象,怎么拷贝了两个呢,而且有一个拷贝完就释放了,还有一个是主线程退出后才释放的,初步结论是使用 bind,第一个参数会拷贝一份,立即释放,第二个参数再拷贝一份,主线程退出后才释放。
所以再调用一遍f1(),改变的肯定是拷贝出来的对象中i的值。

void testFunction()
{
	TestRef t1;
	TestRef1 t2;
	function<void()> f1 = bind(funs, t1, ref(t2));
	f1();
	cout << "testFunction " << "t1:" << &t1 << " " << t1.i << " t2:" << " " << &t2 << " " << t2.i << endl;
	f1();
	cout << "testFunction " << "t1:" << &t1 << " " << t1.i << " t2:" << " " << &t2 << " " << t2.i << endl;
}

C++ ref和引用(&)_第3张图片
可以清晰的看到荧光绿是t1对象,而红色是构造出来的对象test1,多次调用f1(),其中test1都是第一次构造的那个对象,并且i累加了,但是在testFunction中t1中i的值依旧是0。t2和test2一直用的都是一个地址,也就是同一个对象,这也证实了上述的结论。

至于线程thread中参数使用ref,自己动手看下结果吧,实践出真知

你可能感兴趣的:(C/C++)