自理解并区分临时对象,局部变量,栈上对象等概念

在学习C++的过程中,经常遇到这样几个概念:临时对象,局部变量,栈上对象等等,相信有不少人对此的理解是有点模糊的,只知其一不知其二。刚刚自己悟到了这个点,来说明一下。

1.临时对象、栈上对象

以一个示例引入:

//代码1
Point3D convert(Point2D & d2)
{
    return Point3D(d2); //Point3D(d2)为一个临时对象,将其返回
}

该函数返回一个临时对象,临时对象在哪里呢?是不是在栈上呢?

在我的学习中,是这样的:临时对象,通常是不可以取地址的对象,即CPU中计算产生的中间变量,通常称为右值。常见的临时对象有常量,表达式,函数返回值,等等。

同时有一种专门创建临时对象的写法,格式:类型(值);,如int(5);,A(10);//这里的A为一个类。

临时对象,创建在CPU寄存器上,不会在内存中占空间,因而也不能够取地址(只有内存才有地址编址)。所以临时对象并不是栈上对象——临时对象存在CPU寄存器中,怎么可能跑到栈区呢!

那么上面的代码如何理解呢?不妨再看一个类似的代码:

//代码2
Complex operator+(const Complex & one,const Complex & another)
{
    Complex sum; //栈上对象
    sum.real = one.real + another.real;
    sum.image = one.image + anther.image;
    return sum; //栈上对象可以返回,但不能返回其引用
}

在C++学习过程中,需要铭记的一个知识点是:可以返回栈上对象,但是不可以返回栈上对象的引用。因为引用是和空间相关联的,栈上对象空间的特点是随用随开,用完即消。这段代码中,首先栈上对象sum要拷贝复制一份给临时对象,这就要走拷贝构造了,然后再由临时对象完成函数调用点处的赋值等操作。你要记住在这个过程中会在CPU寄存器里创建一个临时对象,或者叫中间对象。另外,返回的是栈上对象,但是返回到函数调用点处的就是临时对象了,由此临时对象来对调用点处的栈上对象完成赋值或其他操作。

好了,再去看开头那段小小的代码:Pointe3D(d2);本身就是一个临时对象,就存在CPU寄存器里,现在直接将其返回到函数调用点处即可。同样返回到调用点处的是一个临时对象,来对调用点出的栈上对象完成赋值等操作。

栈上对象可以返回,临时对象也可以返回,但是返回到函数调用点处的终究是一个临时对象(突然发现自己也说出了一句”咒语“,哈哈~)

与代码2形成对比的是:

//代码3
//这是运算符重载做类的成员函数
Complex & operator+=(const Complex & another)
{
    this->real += another.real;
    this->image += another.image;
    return *this; //返回当前对象
}

这里返回值类型加上了引用,是因为当前对象的生命周期并不会随着此成员函数的结束而结束。一般在参数位置和返回值位置,传递对象的时候为了避免拷贝构造,要传递对象的引用,此过程也不会产生临时对象。传递引用,就相当于扩大了该对象的作用域。

再论C++中“可以返回栈上对象,但不可以返回栈上对象的引用”:在C语言中有类似的话,C语言说“栈上变量可以返回,本质也是拷贝一份,但是不可以返回栈上空间,因为栈上空间随用随开用完即消,生命周期比较短。不可以返回栈上对象的引用 和 不可以返回栈上空间 本质是一样的,因为引用关联的就是空间啊!

2.局部变量

局部变量是比较简单的,一般都是在函数体内创建的变量或者对象,为栈上对象。

注:本文中的变量和对象不做严格区分,只是在C中多是变量,在C++中多为对象。如局部变量也可以叫做局部对象,临时对象也可以叫做中间变量。

PS:C/C++是一门有意思并且神奇的编程语言,接近于底层的特点让我们更能理解计算机运行程序的本质。

  写得不好,请多指教!

发布了34 篇原创文章 · 获赞 22 · 访问量 7199

猜你喜欢

转载自blog.csdn.net/lizun7852/article/details/87941071