运行环境:
OS : Ubuntu 16.04 Desktop
G++ Version:gcc version 5.4.0 20160609(Ubuntu 5.4.0-6ubuntu1~16.04.9)
匿名变量:这种变量其实是程序员看不见的,是编译器为了代码正确实行,自动会在代码里面添加的内容(匿名变量)。在C语言里面经常使用return这条语句,但是在C+中,简单的return确实比想象中的复杂。
赋值运算:赋值是在已有的空间中操作,会调用operator = 函数。
类初始化:初始化是分配空间并且赋值,会调用copy construct函数(依据情况)。
假设一个函数或者执行体返回一个变量,这个变量又不是int char double等基本类型,是一个复杂类型classstruct,如何把“数据块”有效的返回给使用者,又如何把数据块传递给函数。这些问题都和匿名变量相关。在这里不想普及右值,左值将亡值等概念只是从函数的语法结合一点语义去理解。
从一个重载说起:
T & operator=(T &obj){
}
当在类中重载了=号,那么当编译器遇到
T ta ;
T tb;
ta = tb;
这样的代码后会使用用户自己定义的重载赋值运算 = 完成运算。编译器会这样处理:
ta.operator(&tb);ta是一个类的实体。会调用本类中的赋值方法。即=号。我们可以理解为一个函数,这个函数的作用就是把用参数来完成目标类的成员或这内容。一个再简单不过的运算符号重载怎么可以和匿名变量联系在一起?
假设我们定义了重载操作函数:
T operator=(T &obj){
}
会发生什么事情?
执行ta=tb;后会发现产生了一个匿名的变量,在operator=执行后立即析构掉。那为什么在返回引用和返回值得情况下会不一样?这里要说明一下,不要和函数返回“值“和返回“引用“混淆。应为在函数返回值这样的语法下,编译器是会给代码做优化。所谓的优化就是减少不必要的匿名变量,减少不必要的拷贝函数。
这是个人理解:既然函数返回了,而且是返回值,一定有个临时变量与之对应。这样就是右值或者叫将亡值。执行后语句后立即消失(析构)。但是返回引用却不一样,应为返回的是一个别名。可以理解为一个临时变量的别名,临时变量的生命周期很短,所以这个别名也没有必要与之对应生成一个临时变量。至于使用“值”返回后,这个变量到底有没有作用,我觉的最好的例子就是:
或者有这样的表达式:
class t{
t(class t &obj){}
}
t b;
t a(b);
假设可以变形为:a.copy_construct(&b);
这样是不是会有临时变量?我觉的会有,但是这个临时变量就是a本生。也就是说用b来初始化a。在a退出具体作用区域后也会被析构,这个a才是临时变量。而匿名变量是看不着摸不到的。直接以相同参数调用相关构造函数构或者直接调用拷贝构造函数到目标对象。C++编译器又这样的优化能力。
两个表达式都是初始化另外一个变量,但是C++真的很拗口,很晦涩。返回值,返回的是什么,可以是类,可以是基本类型。在基本类型中我们只要简单的处理压栈的数据,只要保证数据在函数出栈以后能继续访问就可以,似乎从来不考虑效率的问题,但是C++不一样,More than C。而且这些问题在使用C语言时候也从没有考虑过。
接着在聊聊函数返回的情况:
T func()或者
T & func()
T a = func()
或者这样的表达式
T a;
a = func();
#include
using namespace std;
class test
{
int age;
public:
test():age(0){
cout<<"test construct "<age = obj.age;
}
test(const test && obj)
{
cout<<&obj<<" from rvalue construct to "<
分别使用局部变量和全局变量来说名问题。在局部变量编译后运行过过程中程序会发生错误,但是先搁置一下,主要是看看编译器有没有分配匿名变量。并且如何对待初始化和赋值操作。
{
执行过程:
test te(3);
cout<<"in function "<<&te<
执行过程:
testconstruct parm 0x7ffff0160750
(3)初始化类通过全局变量返回值:
(4)初始化类通过全局变量返回引用: