首页 > 编程语言 >C++左值引用、右值引用、移动语义、完美转发、深浅拷贝

C++左值引用、右值引用、移动语义、完美转发、深浅拷贝

时间:2024-02-17 12:44:34浏览次数:27  
标签:右值 对象 左值 引用 拷贝 构造函数

一、左值和右值定义(能否取地址
1.左值:可以取地址的对象
2.右值:不可以取地址、临时要销毁的对象

二、左值引用
1.定义:对左值的引用

int& ra = a;

2.作用:传递参数和返回值时减少不必要的拷贝

三、右值引用
1.定义:对右值的引用

// 以下是对几种右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);

2.作用
(1)移动语义:减少两个对象交互时不必要的拷贝,节省运算存储资源,提高效率
(2)完美转发:更加简洁准确地定义泛型函数

四、移动语义中的移动构造函数
定义:移动构造函数是一个接受右值引用参数的构造函数,它用于将资源从一个对象转移到另一个对象。移动构造函数的实现通常会“窃取”源对象的资源,并将源对象的资源指针(或其他表示资源的成员)置为空,从而确保源对象不再拥有这些资源。

class MyObject {
public:
    // 移动构造函数
    MyObject(MyObject&& other) noexcept {
        // 窃取资源
        resource_ = other.resource_;
        other.resource_ = nullptr; // 将源对象的资源指针置为空
    }

    // 其他成员和方法...
private:
    Resource* resource_; // 假设Resource是一种动态分配的资源类型
};

五、完美转发
泛型函数是一种能够在不指定具体类型的情况下工作的函数,它们通常使用模板来实现。泛型函数允许在编写代码时延迟类型的指定,使得函数可以处理各种不同类型的数据。
右值引用可以更简洁明确地定义泛型函数,因为它们提供了对右值的特定支持,使得函数能够在不必要的拷贝的情况下处理临时对象。在C++11之前,泛型函数可能会导致对传递的参数进行不必要的深拷贝,特别是对于临时对象(右值)的处理。而右值引用使得我们可以针对右值和左值分别进行优化,从而避免了不必要的资源拷贝。
举例来说,考虑一个简单的模板函数,该函数接受一个参数并返回其两倍值:

template<typename T>
T doubleValue(T value) {
    return value * 2;
}

在这个函数中,无论传递的是左值还是右值,参数都会被复制一次,这可能会导致性能损失,特别是对于大型对象或临时对象而言。
通过使用右值引用,我们可以更明确地指定函数接受右值参数,并对其进行优化:

template<typename T>
T doubleValue(T&& value) {
    return value * 2;
}

现在,这个函数可以接受左值和右值,并根据参数类型进行适当的优化。如果传递的是右值,那么不会发生额外的拷贝,因为右值引用允许我们在需要时直接访问临时对象。这使得函数更加灵活和高效,同时也更清晰地表达了函数的意图,即该函数可以接受任意类型的参数,并返回其两倍值,而不会产生不必要的开销。

六、浅拷贝和深拷贝(有无资源的重新分配)
1.浅拷贝只复制指针或引用,将源对象的值拷贝到目标对象中去,本质上来说源对象和目标对象共用一份实体,只是所引用的变量名不同,地址其实还是相同的,因此复制后的对象共享相同的资源。
2.拷贝的时候先开辟出和源对象大小一样的空间,然后将源对象里的内容拷贝到目标对象中去,这样两个指针就指向了不同的内存位置,并且里面的内容是一样的。

class ShallowCopy {
public:
    int* data;

    // 构造函数
    ShallowCopy(int val) {
        data = new int(val);
    }

    // 拷贝构造函数(浅拷贝)
    ShallowCopy(const ShallowCopy& other) {
        data = other.data; // 只复制指针,而不是分配新的内存
    }  

    // 拷贝构造函数(深拷贝)
    DeepCopy(const DeepCopy& other) {
        data = new int(*other.data); // 分配新的内存并复制数据
    }

    // 析构函数
    ~ShallowCopy() {
        delete data;
    }
};

标签:右值,对象,左值,引用,拷贝,构造函数
From: https://www.cnblogs.com/fly-smart/p/18017891

相关文章

  • SharePoint Online 中Excel引用另一个Excel中的单元格
    前言最近,碰到一个需求,用户想要在SharePointOnline中从一个Excel文件引用另一个Excel文件的内容,所以就研究了一下。正文1.建一个测试的Excel文件,随便写点东西,如下图:2.新建另一个Excel,用来引用上一个Excel文件,如下图:3.在第一个Excel中的文件,选中单......
  • 右值
    右值每个C++表达式都有一个类型,属于值类别。值类别是编译器在表达式计算期间创建、复制和移动临时对象时必须遵循的规则的基础。C++17的值类别有:glvalue(generalizedlvalue):表示对象身份的表达式,如变量名、函数名、类名等(包括具名右值引用,匿名右值引用比如std::move(x)......
  • Python中的包模块引用成员的方法
    在Python中,包(package)和模块(module)是组织和管理代码的重要方式。将代码分成不同的模块或包可以更好地组织代码结构,使代码更易于维护和管理。说的通俗点,就是将代码整理成一块一块,然后使用时候相互拼接完成就可以使用,这样的好处是可用性高而且非常方便维护,尤其是在选择大型爬虫项目的......
  • react引用async异步函数数据渲染
    当需要在React组件中引用异步函数获取的数据时,可以使用useState钩子来存储数据,并在组件渲染时进行处理。下面是一个示例,展示了如何在React中引用异步函数的数据并进行渲染:importReact,{useState,useEffect}from'react';functionMyComponent(){const[data,......
  • Java的软引用、弱引用和强引用学习
    一、强引用强引用可以直接访问目标对象,所指向的对象在任何时候都不会被系统回收,JVM宁愿抛出OOM异常也不会回收强引用所指向的对象,但是有可能会导致内存泄漏。packagelearn;/***@authorqx*@date2024/1/5*@des*/publicclassDemo{publicstaticvoidmain(S......
  • 右值引用
    右值每个C++表达式都有一个类型,属于值类别。值类别是编译器在表达式计算期间创建、复制和移动临时对象时必须遵循的规则的基础。C++17的值类别有:glvalue(generalizedlvalue):表示对象身份的表达式,如变量名、函数名、类名等。prvalue(purervalue):表示纯右值的表达式,如字......
  • vs2015nuget中卸载组件,提示未将对象引用设置到对象的实例
     报错“未将对象引用设置到对象的实例”是一个常见的.NET错误,通常表示尝试使用了一个还没有被实例化的对象。在VisualStudio2015中使用NuGet进行组件卸载时遇到这个错误,可能是因为NuGet的操作出现了问题,或者是项目文件(.csproj)或包管理文件(.nuget/NuGet.config)中存......
  • 在网站项目中引用 Bootstrap 5字形图标
    Bootstrap图标库是由Bootstrap团队官方维护的免费、开源、高质量图标库,可以以SVG矢量图、SVGsprite或web字体三种形式来使用。截止2024年2月,Bootstrap5 1.11.3版中有2054多个字形图标,该图标库正在不断丰富中。在Visualstudio中创建ASP.NETCore或者MVC项目模板中,并......
  • Nginx--引用多配置文件
    在nginx.conf的http模块,include指定某个目录下的*.confusernginx;worker_processesauto;error_log/var/log/nginx/error.log;pid/run/nginx.pid;#Loaddynamicmodules.See/usr/share/nginx/README.dynamic.include/usr/share/nginx/modules/*.conf;events{......
  • c++11的左值 右值的笔记
    在C++11的程序中,所有的值必须属于左值,将亡值,纯右值之一。将忘值则是c++11新增的跟右值引用相关的表达式,这样表达式通常是将要被移动的对象(以为他用),比如返回右值引用T&&的函数返回值,std::move的返回值,或者转换为T&&的类型的转换函数的返回值。而剩余的,可以标识函数、对象的值都属......