C++实例分析讲解临时对象与右值引用的用法

目录

1.什么是临时变量

2.右值引用

2.1概念

2.2代码实现

2.3C++11新特性之移动构造

2.3.1移动构造函数的介绍

2.3.2代码实现

1.什么是临时变量

在栈上定义对象时,当只调用类中的构造函数时,编译器将在栈上创建一个临时对象,这个临时对象没有地址。所以他的生命周期非常短。短到下一行代码就被直接析构了。

代码验证

#include <iostream> using namespace std; class A { public: A() { cout<<"A的构造"<<endl; } virtual ~A() { cout<<"A的析构"<<endl; } A(const A& other) { cout<<"A的拷贝构造"<<endl; } virtual void show_info() { cout<<"我是父亲"<<endl; } }; class B:public A { public: B() { cout<<"B的构造"<<endl; } ~B() { cout<<"B的析构"<<endl; } void show_info() { cout<<"我是父亲"<<endl; } }; int main() { A a=B(); a.show_info(); return 0; }

结果图:

如图所示,现在我们来分析结果,首先这是一个拷贝构造,拷贝构造指的是用一个已经初始化的值,去初始化另一个没有初始化的值,前两行的构造都是临时变量的构造,然后开始拷贝构造,拷贝构造完成之后,立马对两个临时构造进行析构,这个就证明了当只调用类中的构造函数时,编译器将在栈上创建一个临时对象,最后一个析构是拷贝构造的析构。

像这种情况我们就无法使用这个临时变量,我们可以通过const常引用的方式来解决,我们都知道,我们无法直接int &a=100,无法直接引用一个常量,这个时候我们可以const int &a=100;所以,我们用这个方法来实现一下,代码如下:

但是这个时候我们会发现,常引用只能引用常函数,所以我们还必须把引用的函数加上const,但是这个在工作过程中,基本上是不现实,也是不方便的。

#include <iostream> using namespace std; class A { public: A() { cout<<"A的构造"<<endl; } virtual ~A() { cout<<"A的析构"<<endl; } A(const A& other) { cout<<"A的拷贝构造"<<endl; } virtual void show_info()const { cout<<"我是父亲"<<endl; } }; class B:public A { public: B() { cout<<"B的构造"<<endl; } ~B() { cout<<"B的析构"<<endl; } void show_info()const { cout<<"我是父亲"<<endl; } }; int main() { const A& a=B(); a.show_info(); return 0; }

结果图:

虽然我们得到了这样一个结果图,但是这是不方便得,所以我们就引出来了右值引用。

注意:此时B()已经不是一个临时变量了,他有了地址,所以,现在这个就相当于

//相当于const A& a=B(); int temp=&B的地址,把B的地址进行保存。注意这个是在栈上。 //可能有些人会这么理解 B* b=new B; A&& a=std::move(*(b)); a.show_info(); //但是我们注意了右值引用不能用在堆上,并且这种写法肯定也是不对的

成为了多态的一个条件了。

2.右值引用 2.1概念

左值:有地址的量就是左值。

右值:没有地址量就是右值。

右值引用的语法形式:

右值引用类型&& 引用变量 = 常量或临时对象

2.2代码实现 #include <iostream> using namespace std; class A { public: A() { cout<<"A的构造"<<endl; } virtual ~A() { cout<<"A的析构"<<endl; } A(const A& other) { cout<<"A的拷贝构造"<<endl; } virtual void show_info() { cout<<"我是父亲"<<endl; } }; class B:public A { public: B() { cout<<"B的构造"<<endl; } ~B() { cout<<"B的析构"<<endl; } void show_info() { cout<<"我是父亲"<<endl; } }; int main() { A&& a=B(); a.show_info(); //也可以使用, A&& a1=std::move(a); a.show_info(); return 0; }

结果图:

用了右值引用我们就可以不用在加const了,也是我们工作开发中常用的。

注意:我在这个代码里面写了两个可以调用多态的方法,第二个方法,如果一个右值想引用一个左值时,必须使用std::mover函数,此时如果不加A&&,相当于一个拷贝构造。

2.3C++11新特性之移动构造 2.3.1移动构造函数的介绍

1.首先我们讨论一下移动构造函数的优缺点,有了移动构造我们就不用再开辟新的空间,提高了效率,但是也有它的缺点,缺点就是这玩意不是很安全,我们可以在这个里面修改这个值,可能会导致一些问题。

2.就是我们可能会想为什么我们不能把这个移动构造的逻辑直接,加入到拷贝构造中呢,只需要把const直接去掉不就一样的了麻,但是如果我们把const去掉之后,我们other就不能是个常数了,这样就导致了缺点,所以,移动构造函数是拷贝函数的一个优化补充。

2.3.2代码实现 #include <iostream> using namespace std; class A { int *a; public: A():a(new int[1024]) { cout<<"A的构造"<<endl; } A(const A& other) { a=new int[1024]; memcpy(this->a,other.a,sizeof (int[1024])); } A(A&& other) { this->a=other.a; other.a=nullptr; cout<<"A的移动构造"<<endl; } ~A() { if(a!=nullptr){ delete [] a; cout<<"A的析构"<<endl; } } }; int main() { A a; A a1=std::move(a); return 0; }

结果图:

这样就只析构了一次就是正确的了。

到此这篇关于C++实例分析讲解临时对象与右值引用的用法的文章就介绍到这了,更多相关C++临时对象与右值引用内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    Python之可迭代对象、迭代器、生成器

    Python之可迭代对象、迭代器、生成器,迭代,生成器,一、概念描述可迭代对象就是可以迭代的对象,我们可以通过内置的iter函数获取其迭代器,可

    应用程序对象

    应用程序对象,,应用程序对象是一个应用程序级对象,用于在所有用户之间共享信息,并且在Web应用程序运行期间可以保存数据。 应用的性质: 方法

    Java创建对象的几种方式

    Java创建对象的几种方式,对象,方法,本文目录Java创建对象的几种方式java中几种创建对象的方式1Java中创建对象的集中方式有那些JAVA创建对

    wps快速的编辑图层|WPS巧用对象图层

    wps快速的编辑图层|WPS巧用对象图层,图层,编辑,快速,wps,1.WPS 如何巧用对象图层一、认识对象图层工具及按纽1、您可以在插件工具栏中可以

    空对象快捷键|空白对象快捷键

    空对象快捷键|空白对象快捷键,,空白对象快捷键以win7系统为例1.在键盘上找到Ctrl➕alt➕delete同时按下2.出现下图界面后,在右下角找到红色

    选择对象快捷键|对象全选的快捷键

    选择对象快捷键|对象全选的快捷键,,对象全选的快捷键第一种最常用最实用的Ctrl+鼠标多选单击选择一个文件夹或文件,然后左手按着“Ctrl”键

    ai对象对齐快捷键|ai智能对象快捷键

    ai对象对齐快捷键|ai智能对象快捷键,,1. ai智能对象快捷键找到“分割下方对象”,点击快捷键,然后同时按住“ctrl+1”,里面只要显示了,那就是可