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

 更新时间:2022年08月16日 10:51:49   作者:lhb2998658795  
对性能来说,许多的问题都需要和出现频率及本身执行一次的开销挂钩,有些问题虽然看似比较开销较大,但是很少会执行到,那也不会对程序有大的影响;同样一个很小开销的函数执行很频繁,同样会对程序的执行效率有很大影响。本章中作者主要根据临时对象来阐述这样一个观点

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++临时对象与右值引用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中priority_queue模拟实现的代码示例

    C++中priority_queue模拟实现的代码示例

    在c++语言中数据结构中的堆结构可以通过STL库中的priority_queue 优先队列来实现,这样做极大地简化了我们的工作量,这篇文章主要给大家介绍了关于C++中priority_queue模拟实现的相关资料,需要的朋友可以参考下
    2021-08-08
  • C语言 动态内存分配详解

    C语言 动态内存分配详解

    这篇文章主要介绍了C语言 动态内存分配详解的相关资料,需要的朋友可以参考下
    2017-06-06
  • C/C++实现跨文件共享全局变量详解

    C/C++实现跨文件共享全局变量详解

    这篇文章主要为大家详细介绍了C/C++如何实现跨文件共享全局变量,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • C++实现打地鼠游戏设计

    C++实现打地鼠游戏设计

    这篇文章主要为大家详细介绍了C++实现打地鼠游戏设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • 深入浅析C++中的#,##,和

    深入浅析C++中的#,##,和

    这篇文章主要介绍了C++中的#,##,和"的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-09-09
  • C++结构体案例练习分享

    C++结构体案例练习分享

    这篇文章主要和大家分享几个C++ 结构体的案例练习,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下,希望能够给你带来帮助
    2022-04-04
  • C++实现转置矩阵的循环

    C++实现转置矩阵的循环

    大家好,本篇文章主要讲的是C++实现转置矩阵的循环,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • 浅谈C++变量作用域

    浅谈C++变量作用域

    这篇文章主要介绍了C++变量作用域的的相关资料,文中代码非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • C语言链表完整操作演示

    C语言链表完整操作演示

    这篇文章主要为大家详细介绍了C语言链表的完整操作演示,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • C++ 实现对象池的具体方法

    C++ 实现对象池的具体方法

    本文主要介绍了C++ 实现对象池的具体方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01

最新评论