c++中构造函数 、析构函数的作用域详解
2015-07-08 12:04
585 查看
我们知道,在c++中,析构函数是在函数作用域尾部执行析构函数,从而释放对象,但是有一种情况下,析构函数作用域发生变化,请看下面的例子,定义了一个Stock类,Stock类存放在stock.h中,主调用函数在stock.cpp中。
stock.h
stock.cpp
可以看到我们声明友元函数plus1后,将object[2]对象通过构造函数传递到友元中,此时友元函数中先调用拷贝构造函数接受参数,然后调用 默认构造函数形成局部total对象,在我们完成加的动作之后,对象要返回,此时调用析构函数,但若此时我们采用引用的返回值方式 Stock &plus1(int stock_num,Stock t) ,调用同样成功,但对象被销毁了,为什么还可以被引用 而继续使用。我们来看一下两种返回方式的结果:
返回对象,
返回对象引用,
此时编译器应该是做过优化,因为函数的作用域结尾处,应该调用过析构函数了(从图中可以看出来,调用了5次构造函数,6次析构函数,有一次复制构造函数),所以析构 函数肯定是被执行了,但是编译器作过优化处理,使得对象依旧可以被传递,此时编译器会给出警告提示。但是在1个函数中,我们可以返回1个在函数调用结束不会被释放的对象的引用。比如外部传入的对象,比如函数所属类的成员变量等。而返回局部变量(对象引用)是很危险的,但是返回对象则是可以的,因为返因对象时会调用复制构造函数、然后才是析构函数。如果我们plus1调用传递的是引用时,此时结果为
,不会调用复制构造函数。当改为值传递后,复制构造函数又被重新调用,
stock.h
#include <iostream> #include <string.h> class Stock{ private: char m_company[30]; 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+1); m_stock_num=stock_num; m_stock_price=stock_price; stock_sum(); } Stock::Stock() { m_stock_num=0; m_stock_price=0; 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>30) return false; strncpy(m_company,company,len+1); 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=0; 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[100]; strcpy(p,"baidu"); Stock object[4]; 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[3]=plus1(100,object[2]); object[3].print_stock_info(); return true; }
可以看到我们声明友元函数plus1后,将object[2]对象通过构造函数传递到友元中,此时友元函数中先调用拷贝构造函数接受参数,然后调用 默认构造函数形成局部total对象,在我们完成加的动作之后,对象要返回,此时调用析构函数,但若此时我们采用引用的返回值方式 Stock &plus1(int stock_num,Stock t) ,调用同样成功,但对象被销毁了,为什么还可以被引用 而继续使用。我们来看一下两种返回方式的结果:
返回对象,
返回对象引用,
此时编译器应该是做过优化,因为函数的作用域结尾处,应该调用过析构函数了(从图中可以看出来,调用了5次构造函数,6次析构函数,有一次复制构造函数),所以析构 函数肯定是被执行了,但是编译器作过优化处理,使得对象依旧可以被传递,此时编译器会给出警告提示。但是在1个函数中,我们可以返回1个在函数调用结束不会被释放的对象的引用。比如外部传入的对象,比如函数所属类的成员变量等。而返回局部变量(对象引用)是很危险的,但是返回对象则是可以的,因为返因对象时会调用复制构造函数、然后才是析构函数。如果我们plus1调用传递的是引用时,此时结果为
,不会调用复制构造函数。当改为值传递后,复制构造函数又被重新调用,
相关文章推荐
- C++对象缺省函数
- C++容器类型
- C++ 怎么取整形数组的长度
- 黑马-C语言-流程控制,循环结构
- 黑马-C语言-关系,逻辑运算
- 如何用C语言封装 C++的类,在 C里面使用
- C++运算符重载的方法详细解析
- c++运算符重载总结
- C++中的内存分区介绍
- C语言常见面试题(经典中的经典)
- C++ Vector用法详解
- C++继承的函数实现
- C++ Primer学习笔记(12)——class和struct 定义的类有什么不同
- [调试][程序打印]当printf不能用时,使用C++的不定参数来搞定OutputDebugString打印
- C语言将24小时制转换为12小时制的方法
- 通过友元函数实现两个不同类中私有成员变量的数据交换
- C++ Primer学习笔记(11)——(转)c++ 标准库的各种容器(vector,deque,map,set,unordered_map,unordered_set,list)的性能考虑
- C/C++宏定义中#与##区别
- 【c语言】数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字
- quick_sort(快速排序)c语言实现