我们知道,在c++中,析构函数是在函数作用域尾部执行析构函数,从而释放对象,但是有一种情况下,析构函数作用域发生变化,请看下面的例子,定义了一个Stock类,Stock类存放在stock.h中,主调用函数在stock.cpp中。
stock.h
1 #include <iostream> 2 #include <string.h> 3 class Stock{ 4 private: 5 char m_company[30]; 6 int m_stock_num; 7 float m_stock_price; 8 float total_price; 9 float stock_sum(){total_price= m_stock_num*m_stock_price;} 10 11 public: 12 int get_stock(char *company,int stock_num,float stock_price); 13 void increase(int num,float price); 14 void sell(int num,float price); 15 void update_price(float price); 16 void print_stock_info(); 17 friend Stock plus1(int stock_num,Stock t); 18 Stock operator+(Stock t); 19 Stock(char *p,int num,float price); 20 Stock(); 21 ~Stock(); 22 }; 23 24 Stock::Stock(char *company,int stock_num,float stock_price) 25 { 26 int len=strlen(company); 27 strncpy(m_company,company,len+1); 28 m_stock_num=stock_num; 29 m_stock_price=stock_price; 30 stock_sum(); 31 32 } 33 34 Stock::Stock() 35 { 36 m_stock_num=0; 37 m_stock_price=0; 38 stock_sum(); 39 std::cout<<"hello boy"<<std::endl; 40 } 41 42 Stock::~Stock() 43 { 44 std::cout<<"good bye"<<std::endl; 45 46 } 47 48 Stock plus1(int stock_num,Stock t) 49 { 50 Stock total; 51 total.m_stock_num=stock_num+t.m_stock_num; 52 return total; 53 54 } 55 56 57 inline Stock Stock::operator+(Stock t) 58 { 59 Stock total; 60 total.m_stock_num=m_stock_num+t.m_stock_num; 61 total.total_price=total_price+t.total_price; 62 return total; 63 } 64 65 inline int Stock::get_stock(char * company,int stock_num,float stock_price) 66 { 67 int len=strlen(company); 68 if (len>30) 69 return false; 70 strncpy(m_company,company,len+1); 71 m_stock_num=stock_num; 72 m_stock_price=stock_price; 73 stock_sum(); 74 return true; 75 } 76 77 void Stock::increase(int num,float price) 78 { 79 m_stock_num=m_stock_num+num; 80 m_stock_price=price; 81 stock_sum(); 82 } 83 84 void Stock::sell(int num,float price) 85 { 86 if(num>m_stock_num) 87 m_stock_num=0; 88 else 89 m_stock_num=m_stock_num-num; 90 91 m_stock_price=price; 92 stock_sum(); 93 } 94 void Stock::update_price(float price) 95 { 96 m_stock_price=price; 97 98 } 99 void Stock::print_stock_info() 100 { 101 std::cout<<m_stock_num<<std::endl; 102 std::cout<<total_price<<std::endl; 103 }
stock.cpp
1 #include "stock.h" 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 int main() 6 { 7 char *p; 8 p=new char[100]; 9 strcpy(p,"baidu"); 10 Stock object[4]; 11 object[0].get_stock(p,100,2.3); 12 object[1].get_stock(p,100,2.3); 13 object[2]=object[0]+object[1]; 14 object[2].print_stock_info(); 15 object[3]=plus1(100,object[2]); 16 object[3].print_stock_info(); 17 return true; 18 19 }
可以看到我们声明友元函数plus1后,将object[2]对象通过构造函数传递到友元中,此时友元函数中先调用拷贝构造函数接受参数,然后调用 默认构造函数形成局部total对象,在我们完成加的动作之后,对象要返回,此时调用析构函数,但若此时我们采用引用的返回值方式 Stock &plus1(int stock_num,Stock t) ,调用同样成功,但对象被销毁了,为什么还可以被引用 而继续使用。我们来看一下两种返回方式的结果:
返回对象,
返回对象引用,
此时编译器应该是做过优化,因为函数的作用域结尾处,应该调用过析构函数了(从图中可以看出来,调用了5次构造函数,6次析构函数,有一次复制构造函数),所以析构 函数肯定是被执行了,但是编译器作过优化处理,使得对象依旧可以被传递,此时编译器会给出警告提示。但是在1个函数中,我们可以返回1个在函数调用结束不会被释放的对象的引用。比如外部传入的对象,比如函数所属类的成员变量等。而返回局部变量(对象引用)是很危险的,但是返回对象则是可以的,因为返因对象时会调用复制构造函数、然后才是析构函数。如果我们plus1调用传递的是引用时,此时结果为
,不会调用复制构造函数。当改为值传递后,复制构造函数又被重新调用,