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

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

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

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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-02 07:41:47

引用与析构,通过引用减少临时变量的相关文章

c++中临时变量不能作为非const的引用参数

试看下面的代码: #include <iostream> using namespace std; void f(int &a) { cout << "f(" << a  << ") is being called" << endl; } void g(const int &a) { cout << "g(" << a << "

以查询取代临时变量

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42386305         在上一篇文章中介绍了" 内联临时变量".本文将介绍"以查询取代临时变量"这种重构手法.         下面让我们来学习这种重构手法吧. 开门见山         发现:你的程序以一个临时变量保存某一表达式的运算结果. 解决:将这个表达式提炼到一个独立函数中.将这个临时变量的所有引用点替换为对新函

论函数的设计应如何才好,返回临时变量 | 返回引用 | 传递引用

这个就涉及效率的问题,怎么要写,才会尽可能的少调用构造函数. 先设计如下的类 class tempTest{ public: tempTest(){ cout <<"hello tempTest() "<<count++ << endl; } tempTest(tempTest& ){ cout <<"hello copy tempTest() "<<count++ << endl; }

C++函数返回引用、非引用以及临时变量的问题

C++中新增了引用类型,所以函数的返回值可以是引用类型.那么就会有人想问 返回引用类型与返回非引用类型有区别吗? 结论是显然的,而且有明显的区别.尤其初学者会很容易绕进去.让我们先看四个函数原型.以int类型来举例 (1) int fun(...) { return ....//后面跟的是一个引用 } 例如:int fun(int &a) { return a; } (2)int fun(...) { return....//后面跟的是一个非引用 } 例如:int  fun(int a) { r

临时变量作为非const的引用进行参数传递引发的编译错误

1.错误原因即解决办法 Linux环境运行,使用g++编译,观察如下代码,会出现: invalid initialization of non-const reference of type 'std::string&' from a temporary of type 'std::string'的错误. 其中文意思为临时变量无法为非const的引用初始化.也就是在参数传递的过程中,出现错误.出错的代码如下: void print(string& str) { cout<<st

C++参数传递(引用,临时变量)

一般的变量声明时就创建相应的内存空间,该空间用于存储该变量的值.函数进行按值传递时,是将该变量值的拷贝传给函数,因此在函数中将传进来的值改变也不能改变变量的值. 指针变量和按指针传递.指针类型的变量在声明后,根据操作系统的不同创建相应大小的内存空间,该空间上存储的是一个地址,该地址指向一个变量.如果函数按指针进行传递参数,也是将变量的拷贝传进来,但该变量是一个指向某内存单元的地址,对该变量进行解引用操作,改变其内存单元存储的值,即可改变变量解引用后的值. 引用和按引用传递.引用是变量的别名.在声

非const引用不能指向临时变量

没找到具体原因,MSDN看到下面这句,VC是从2008才有这一限制的,感觉就是从语法上对临时变量增加了限定,因为一般说来修改一个临时变量是毫无意义的,通过增加限定,强调临时变量只读语义.虽然实际上修改临时变量并不会有问题. Visual Studio 2008 In previous releases of Visual C++, non-const references could be bound to temporary objects. Now, temporary objects ca

C++ const引用、临时变量 引用参数

C++引用-临时变量.引用参数和const引用 如果实参与引用参数不匹配,C++将生成临时变量.如果引用参数是const,则编译器在下面两种情况下生成临时变量: 实参类型是正确的,但不是左值 实参类型不正确,但可以转换为正确的类型 左值参数是可被引用的数据对象,例如,变量.数组元素.结构成员.引用和被解除引用的指针都是左值,非左值包括字面常量和包含多项式的表达式.定义一个函数 Double refcube(const double& ra) { Returnra*ra*ra; } double

C++11引用临时变量的终极解析

工作中遇到一个引用临时变量的问题,经过两天的学习,私以为:不仅弄明白了这个问题,还有些自己的独到见解. 这里使用一个简单的例子来把自己的学习过程和理解献给大家,如果有什么问题请不吝指正. *************************Code************************* class Dog { public: Dog(){} virtual ~Dog(){} }; void NonConstReference (Dog & dog ) { //tell the dog