• c++中构造函数 、析构函数的作用域详解


      我们知道,在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调用传递的是引用时,此时结果为

    ,不会调用复制构造函数。当改为值传递后,复制构造函数又被重新调用,

  • 相关阅读:
    数字签名与HTTPS详解
    利用策略模式优化过多 if else 代码
    Redis 的事务到底是不是原子性的
    Spring Boot项目的接口防刷
    深入分析 ThreadLocal
    什么是四层和七层负载均衡?他们之间的区别是什么?
    MyEclipse或Eclipse中project的导入和导出
    org.hibernate.exception.ConstraintViolationException: could not insert:
    C++ STL vector(向量容器)的使用(附完整程序代码)
    Swift2.0语言教程之函数嵌套调用形式
  • 原文地址:https://www.cnblogs.com/hitwhhw09/p/4629783.html
Copyright © 2020-2023  润新知