C++_引用与析构,通过引用减少临时变量

通过引用可以大大减少创建临时变量的次数,从而提高程序运行的效率。

本文探讨创建通过引用减少创建临时变量的次数,与临时变量的生命周期。


测试一:不使用引用并且返回的临时变量不用引用保存。


#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x  = ++Point::count;
	}


	~Point(){
		printf("xx %d\n",x);
	}

	Point XX(Point x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	//Point &pz = 
	pt.XX(pk);
	//pz.print();
	pt.print();

	return 0;
}


运行截图


通过以上输出,可以看出发生了4次析构,说明产生了两个临时变量。

3,4为临时变量。

第一个临时变量为3, 3为传递进来的参数调用了复制构造函数,

生命周期:在函数执行完成后即进行析构。

第二个临时变量为4, 4为返回的参数, 其调用了复制构造函数

生命周期:在完成对原有变量赋值(隐含复制操作)即进行析构。




测试二:不使用引用并且返回的临时变量并使用引用保存。

#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x = ++Point::count;
	}


	~Point(){
		printf("xx %d\n", x);
	}

	Point XX(Point x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	Point &pz = pt.XX(pk);
	//pz.print();
	pt.print();

	printf("haha\n");

	return 0;
}



运行截


通过以上输出,可以看出发生了4次析构,说明产生了两个临时变量。

3,4为临时变量。

第一个临时变量为3, 3为传递进来的参数调用了复制构造函数,

生命周期:在函数执行完成后即进行析构。

第二个临时变量为4, 4为返回的参数, 其调用了复制构造函数

生命周期:在完成对原有变量赋值(隐含复制操作)由于又使用了引用对其(临时变量)保存,故该临时变量生存周期同引用生存周期。

在函数最后进行析构,但由于声明变量的顺序与析构顺序相反,析构序号为4,2,1



测试三:对传进来的参数使用引用,返回值不使用引用,返回的临时变量(引用)使用引用保存。

#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x = ++Point::count;
	}


	~Point(){
		printf("xx %d\n", x);
	}

	Point XX(Point &x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	Point &pz = pt.XX(pk);
	//pz.print();
	pt.print();

	printf("haha\n");

	return 0;
}



通过以上输出,可以看出发生了3次析构,说明产生了一个临时变量。

3为临时变量。

第一个临时变量3, 3为返回的参数, 其调用了复制构造函数

生命周期:在完成对原有变量赋值(隐含复制操作)由于又使用了引用对其(临时变量)保存,故该临时变量生存周期同引用生存周期。

在函数最后进行析构,但由于声明变量的顺序与析构顺序相反,析构序号为3,2,1



测试四:对传进来的参数不使用引用,返回值使用引用,返回的临时变量(引用)使用引用保存。

#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x = ++Point::count;
	}


	~Point(){
		printf("xx %d\n", x);
	}

	Point& XX(Point x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	Point &pz = pt.XX(pk);
	//pz.print();
	pt.print();

	printf("haha\n");

	return 0;
}


通过以上输出,可以看出发生了3次析构,说明产生了一个临时变量。

3为临时变量。

第一个临时变量3, 3为传递进去的对象, 其调用了复制构造函数

生命周期:在函数调用的时候使用了复制构造函数,函数执行完成后立即进行析构。




测试五:对传进来的参数使用引用,返回值使用引用, 返回的临时变量(引用)使用引用保存。

#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x = ++Point::count;
	}


	~Point(){
		printf("xx %d\n", x);
	}

	Point& XX(Point &x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	Point &pz = pt.XX(pk);
	//pz.print();
	pt.print();

	printf("haha\n");

	return 0;
}


通过以上输出,可以看出发生了2次析构,说明没产生临时变量。



测试六:对传进来的参数不使用引用,返回值使用引用,返回的临时变量(引用)使用引用保存。

#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x = ++Point::count;
	}


	~Point(){
		printf("xx %d\n", x);
	}

	Point& XX(Point x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	Point &pz = pt.XX(pk);
	pz.print();
	pt.print();

	printf("haha\n");

	return 0;
}


通过以上输出,可以看出发生了3次析构,说明产生了一个临时变量。

3为临时变量。

第一个临时变量3, 3为传递进去的对象, 其调用了复制构造函数

生命周期:在函数调用的时候使用了复制构造函数,函数执行完成后立即进行析构。而我使用一个引用对返回的临时变量进行了保存,但在完成

赋值之后

Point &pz = pt.XX(pk);

即这条语句之后,该临时变量进行了析构,之后调用的print 函数打出了被释放后的内存区域,需要十分注意



测试七:对传进来的参数使用引用,返回值不使用引用,返回的临时变量(引用)使用引用保存。

#include <cstdio>
#include <iostream>

using namespace std;


class Point{
private:
	static int count;
	int x;

public:
	Point() {
		printf("constructor called\n");
		x = ++Point::count;
	}

	Point(const Point &B){
		printf("copy constructor called\n");
		x = ++Point::count;
	}


	~Point(){
		printf("xx %d\n", x);
	}

	Point XX(Point &x)
	{
		//this->x = 0;

		return x;
	}

	void print()const{
		printf("%d\n", x);
	}


};

int Point::count = 0;

int main(){
	Point pt;
	Point pk;
	Point &pz = pt.XX(pk);
	pz.print();
	pt.print();

	printf("haha\n");

	return 0;
}


通过测试1-6,我们不难发现由于返回的对象为赋值的对象,该临时对象的生命周期为引用的生命周期,所以在pritnf("haha\n");

后进行释放,即main结束时进行释放。




通过以上测试,可以看出

1.若函数传递的参数为对象,且需要返回该对象。

应该在函数传递参数以及函数返回时都使用引用,这样会减少两次临时变量的产生。(测试一~测试五)


2.若对参数调用复制构造函数,返回使用引用,在赋值完成之后,该复制构造函数产生的临时变量的内存空间就被回收(见测试六)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值