我们知道,在c++中,析构函数是在函数作用域尾部执行析构函数,从而释放对象,但是有一种情况下,析构函数作用域发生变化,请看下面的例子,定义了一个Stock类,Stock类存放在stock.h中,主调用函数在stock.cpp中。
stock.h
#include <iostream>
#include <string.h>
class Stock{
private:
char m_company[];
int m_stock_num;
float m_stock_price;
float total_price;
float stock_sum(){total_price= m_stock_num*m_stock_price;} public:
int get_stock(char *company,int stock_num,float stock_price);
void increase(int num,float price);
void sell(int num,float price);
void update_price(float price);
void print_stock_info();
friend Stock plus1(int stock_num,Stock t);
Stock operator+(Stock t);
Stock(char *p,int num,float price);
Stock();
~Stock();
}; Stock::Stock(char *company,int stock_num,float stock_price)
{
int len=strlen(company);
strncpy(m_company,company,len+);
m_stock_num=stock_num;
m_stock_price=stock_price;
stock_sum(); } Stock::Stock()
{
m_stock_num=;
m_stock_price=;
stock_sum();
std::cout<<"hello boy"<<std::endl;
} Stock::~Stock()
{
std::cout<<"good bye"<<std::endl; } Stock plus1(int stock_num,Stock t)
{
Stock total;
total.m_stock_num=stock_num+t.m_stock_num;
return total; } inline Stock Stock::operator+(Stock t)
{
Stock total;
total.m_stock_num=m_stock_num+t.m_stock_num;
total.total_price=total_price+t.total_price;
return total;
} inline int Stock::get_stock(char * company,int stock_num,float stock_price)
{
int len=strlen(company);
if (len>)
return false;
strncpy(m_company,company,len+);
m_stock_num=stock_num;
m_stock_price=stock_price;
stock_sum();
return true;
} void Stock::increase(int num,float price)
{
m_stock_num=m_stock_num+num;
m_stock_price=price;
stock_sum();
} void Stock::sell(int num,float price)
{
if(num>m_stock_num)
m_stock_num=;
else
m_stock_num=m_stock_num-num; m_stock_price=price;
stock_sum();
}
void Stock::update_price(float price)
{
m_stock_price=price; }
void Stock::print_stock_info()
{
std::cout<<m_stock_num<<std::endl;
std::cout<<total_price<<std::endl;
}
stock.cpp
#include "stock.h"
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char *p;
p=new char[];
strcpy(p,"baidu");
Stock object[];
object[0].get_stock(p,100,2.3);
object[1].get_stock(p,100,2.3);
object[2]=object[0]+object[1];
object[2].print_stock_info();
object[]=plus1(,object[]);
object[].print_stock_info();
return true; }
可以看到我们声明友元函数plus1后,将object[2]对象通过构造函数传递到友元中,此时友元函数中先调用拷贝构造函数接受参数,然后调用 默认构造函数形成局部total对象,在我们完成加的动作之后,对象要返回,此时调用析构函数,但若此时我们采用引用的返回值方式 Stock &plus1(int stock_num,Stock t) ,调用同样成功,但对象被销毁了,为什么还可以被引用 而继续使用。我们来看一下两种返回方式的结果:
返回对象,
返回对象引用,
此时编译器应该是做过优化,因为函数的作用域结尾处,应该调用过析构函数了(从图中可以看出来,调用了5次构造函数,6次析构函数,有一次复制构造函数),所以析构 函数肯定是被执行了,但是编译器作过优化处理,使得对象依旧可以被传递,此时编译器会给出警告提示。但是在1个函数中,我们可以返回1个在函数调用结束不会被释放的对象的引用。比如外部传入的对象,比如函数所属类的成员变量等。而返回局部变量(对象引用)是很危险的,但是返回对象则是可以的,因为返因对象时会调用复制构造函数、然后才是析构函数。如果我们plus1调用传递的是引用时,此时结果为
,不会调用复制构造函数。当改为值传递后,复制构造函数又被重新调用,