• c++ =号重载及函数返回值临时变量问题


          今天写c++操作符重载发现了一些问题,遂向师兄请教,于是引出一堆问题,讨论过程中,也解了我几个大疑惑。

          首先写一个c++类,如果你不显示实现,c++会帮你实现拷贝,=号重载,无参默认构造函数等三个基本成员函数。

         感觉上拷贝和=号重载其实是一个意思,但是编译器不这么干,这两个是分别实现的。

         无参构造函数是其成员各自调用自己的无参构造函数,如此循环调用下去。

         关于c++的临时变量,这个很诡异,函数的返回值,写过汇编程序的人知道,函数其实就是一个小程序段,被调用的时候先把参数压入栈,接着把返回地址压入栈,函数调用完返回的时候,直接ret,IP=返回地址,继续执行下一条指令(这里面记不太清了,大概是这么个意思),但是函数返回值在哪?木有啊,ret只是把CS:IP恢复位置,返回值存在哪?答案是栈中,有返回值c++创建了一个临时变量存储这个返回值,因为这个临时变量是在运行时创建的,所以只能在栈中。如果想取这个临时变量的引用,那么前面必须加const,不然会报错,但是如果取这个临时变量的地址的话,不用加const,编译器仅仅会报一个警告,所以我们可以修改临时变量,临时变量的作用域(这个很危险,因为这个地址可能存放其他重要东西)。临时变量在栈中会随时被覆盖,不安全。话不多说,上代码:

    #include <iostream>
    using namespace std;
    int x=0;
    
    class Sales_item{
    public:
    string name;
    float  price;
    public:
    
    Sales_item(string name,float price){
    this->name=name;
    this->price=price;
    }
    Sales_item& operator =(const Sales_item &a){
    cout<<"x="<<x<<endl;
    cout<<"left= addresss:"<<this<<",=right address:"<<&a<<endl;
    x+=1;
    return (*this);
    }
    
    Sales_item():name(""),price(0){}
    Sales_item operator +(const Sales_item &a){
     Sales_item result;
    result=a;
    result.name+=" "+a.name;
    result.price+=a.price;
    return result;
    }
    friend istream& operator >>(istream &is,Sales_item &sales);
    friend ostream& operator <<(ostream &os,const Sales_item &sales);
    //friend Sales_item operator +(const Sales_item &a,const Sales_item &b);
    };
    Sales_item global_test("test2",13);
    int main(void){
    Sales_item test(global_test);
    
    //test+global_test;
    Sales_item* result1=&(test+global_test);
    
    cout<<"1:wuming:"<<(*result1)<<endl;
    //cout<<"name address:"<<&(result1->name)<<",price address:"<<&(result1->price)<<endl;
    cout<<"2:wuming:"<<(*result1)<<endl;
    cout<<"name address:"<<&(result1->name)<<",price address:"<<&(result1->price)<<endl;
    result1->name="modify";
    cout<<"3:wuming:"<<(*result1)<<endl;
    cout<<"name address:"<<&(result1->name)<<",price address:"<<&(result1->price);
    
    
    /*注释块一
    Sales_item sales_0;
    sales_0=test+global_test;
    cout<<"sales_0 address:"<<&sales_0;
    */
    /*注释块二
    Sales_item sales=test+global_test;
    cout<<"sales address:"<<&sales;
    */
    
    
    return 0;
    }
    istream& operator >>(istream &is,Sales_item &sales){
    is>>sales.name>>sales.price;
    return is;
    }
    ostream& operator <<(ostream &os,const Sales_item &sales){
    os<<sales.name<<" "<<sales.price;
    return os;
    }

    上面就是代码编译运行的结果,看到了吧,临时变量不可靠,连着输出两次就出错了,值被覆盖了,所以第一个name字段就读不出来了,临时变量取地址会报警告,如果取引用的话前面不加const会报错。

    如果把注释块一注释去掉,同时把上面指针那一块注释掉,看结果:

    执行了2次=号重载操作,第一次把返回值拷贝到临时变量(无名),第二次把临时变量拷贝到sales_0。

    接下来把注释块一注释掉,去掉注释二,看结果:

    可以看到这个只执行了一次拷贝操作,具体原因不知道,猜测可能是编译器的优化吧。

    先写这么多了,c++是个大坑呀,果断学汇编呀,学好了汇编编译下应该更能看出来编译器工作原理。

  • 相关阅读:
    Selenium2+python自动化-查看selenium API
    彻底搞懂scrapy的中间件第二章
    彻底搞懂scrapy的中间件第一章
    爬虫面试题
    爬取58同城二手房数据存储到redis数据库和mysql数据库
    Scrapy操作浏览器获取网易新闻数据
    Scrapy框架中的 UA伪装
    scrapy框架中如何使用selenuim
    基于scrapy中---全站爬取数据----CrawlSpider的使用
    基于百度AI的自然语言处理文字分类
  • 原文地址:https://www.cnblogs.com/huals/p/2747177.html
Copyright © 2020-2023  润新知