今天写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++是个大坑呀,果断学汇编呀,学好了汇编编译下应该更能看出来编译器工作原理。