通过引用可以大大减少创建临时变量的次数,从而提高程序运行的效率。
本文探讨创建通过引用减少创建临时变量的次数,与临时变量的生命周期。
测试一:不使用引用并且返回的临时变量不用引用保存。
#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.若对参数调用复制构造函数,返回使用引用,在赋值完成之后,该复制构造函数产生的临时变量的内存空间就被回收(见测试六)
版权声明:本文为博主原创文章,未经博主允许不得转载。