【送书】【C++11】左值引用和右值引用

这篇具有很好参考价值的文章主要介绍了【送书】【C++11】左值引用和右值引用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【送书】【C++11】左值引用和右值引用


需要云服务器等云产品来学习Linux的同学可以移步/-->腾讯云<--/-->阿里云<--/-->华为云<--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。


   目录

一、新的类功能

1、新的默认成员函数

2、类成员变量初始化

3、强制生成默认函数的关键字default

4、禁止生成默认函数的关键字delete

二、左值和右值

1、左值和左值引用

2、右值和右值引用

2.1右值的别名是左值

2.2模板的万能引用

2.3完美转发

3、左值引用和右值引用的使用场景和意义

3.1左值引用的使用场景

3.2右值引用的使用场景

三、《Git从入门到精通》


一、新的类功能

1、新的默认成员函数

C++11新增了两个类的默认成员函数:移动构造函数和移动赋值运算符重载。

如果你没有手动实现移动构造函数,并且析构函数、拷贝构造、赋值运算符重载均没有手动实现,编译器就会帮你生成一个默认的移动构造函数。默认生成的移动构造函数,对于内置类型进行按字节的值拷贝,对于自定义类型,将会去调用它的移动构造函数,如果这个内置类型并没有移动构造函数,则编译器去调用它的拷贝构造函数。

如果你没有手动实现移动赋值运算符重载,并且析构函数、拷贝构造、赋值运算符重载均没有手动实现,编译器就会帮你生成一个默认的移动赋值运算符重载。默认生成的移动赋值运算符重载,对于内置类型进行按字节的值拷贝,对于自定义类型,将会去调用它的移动赋值运算符重载,如果这个内置类型并没有移动赋值运算符重载,则编译器去调用它的赋值运算符重载。

2、类成员变量初始化

C++11允许在类定义时给成员变量初始缺省值,默认生成构造函数会使用这些缺省值初始化。

3、强制生成默认函数的关键字default

Person(Person&& p)=default;//让编译器强制生成移动构造

4、禁止生成默认函数的关键字delete

例如现在需要禁用某个类的拷贝构造函数,C++98的玩法是将这个类的拷贝构造函数加上私有权限,并且只声明不实现,就可以在类的内部和外部禁用掉拷贝构造。

C++11使用delete关键字禁止生成某个默认构造函数:

A(const A& a)=delete;//防拷贝

二、左值和右值

1、左值和左值引用

变量和解引用得到的变量是左值,我们可以获取它的地址,左值可以出现赋值符号的左边和右边,右值只能出现在赋值符号的右边。

int main()
{
    // 以下的p、b、c、*p都是左值
    int* p = new int(0);
    int b = 1;
    const int c = 2;
    // 以下几个是对上面左值的左值引用
    int*& rp = p;
    int& rb = b;
    const int& rc = c;
    int& pvalue = *p;
    return 0;
}

1. 左值引用只能引用左值,不能引用右值。

2. 但是const左值引用既可引用左值,也可引用右值(权限平移)

int main()
{
    // 左值引用只能引用左值,不能引用右值。
    int a = 10;
    int& ra1 = a;   // ra为a的别名
    //int& ra2 = 10;   // 编译失败,因为10是右值
    // const左值引用既可引用左值,也可引用右值。
    const int& ra3 = 10;
    const int& ra4 = a;
    return 0;
}

2、右值和右值引用

右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名。C++11中将右值划分成纯右值(内置类型表达式的值)和将亡值(自定义类型的表达式的值)

int main()
{
    double x = 1.1, y = 2.2;
    // 以下几个都是常见的右值
    10;
    x + y;
    fmin(x, y);
    // 以下几个都是对右值的右值引用
    int&& rr1 = 10;
    double&& rr2 = x + y;
    double&& rr3 = fmin(x, y);
    // 这里编译会报错:error C2106: “=”: 左操作数必须为左值
    10 = 1;
    x + y = 1;
    fmin(x, y) = 1;
    return 0;
}

1. 右值引用只能引用右值,不能引用左值。

2. 但是右值引用可以引用move以后的左值。

int main()
{
     // 右值引用只能右值,不能引用左值。
     int&& r1 = 10;
     
     // error C2440: “初始化”: 无法从“int”转换为“int &&”
     // message : 无法将左值绑定到右值引用
     int a = 10;
     int&& r2 = a;
     // 右值引用可以引用move以后的左值
     int&& r3 = std::move(a);
     return 0;
}

2.1右值的别名是左值

右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1,这里的rr1是左值。如果不想rr1被修改,可以用const int&& rr1 去引用。(这个特性在移动赋值中也可以体现,移动赋值参数是右值引用,通过交换这个右值引用的对象完成赋值的目的)

int main()
{
     double x = 1.1, y = 2.2;
     int&& rr1 = 10;//rr1其实是一个左值
     const double&& rr2 = x + y;
     rr1 = 20;
     rr2 = 5.5;//报错  
     return 0;
}

因为右值引用的形参是左值,层层传递时,需要将这个形参move为右值:

void push_back(T&& x)//x为左值
{
	insert(end(),move(x));//需要用move转换为右值,不然会去调用左值版本的insert
}    
iterator insert(interator pos,T&& x)//x为左值
{
	node* newnode=new node(move(x));//需要用move转换为右值,不然会去调用左值版本的node构造函数
}
list_node(T&& x)//x是左值
	:_next(nullptr)
    ,_prev(nullptr)
    ,_data(move(x))//需要用move转换为右值,不然会去调用左值版本的T _data的构造函数
{}

不过这样写的话需要左值写一份,右值的写一份,代码重复了。更推荐下面讲的完美转发的写法。

2.2模板的万能引用

【送书】【C++11】左值引用和右值引用

【送书】【C++11】左值引用和右值引用

模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用到完美转发。

2.3完美转发

std::forward 完美转发在传参的过程中保留对象原生类型属性,当然完美转发也是需要在模板的环境下才能生效,如果不是模板,T&& t同样会被识别成右值引用。

万能引用和完美转发必须保证传参时,才实例化对象,如果传参前模板已经被实例化了,将构不成万能引用和完美转发。

【送书】【C++11】左值引用和右值引用

【送书】【C++11】左值引用和右值引用

使用完美转发修改本节2.1中的move写法:凡是需要往下一层传参的,需要保持右值属性的都需要使用完美转发。

template <class T>
void push_back(T&& x)//x可以接收任意类型
{
	insert(end(),std::forward<T>(x));
}    
iterator insert(interator pos,T&& x)///x可以接收任意类型
{
	node* newnode=new node(std::forward<T>(x));
}
list_node(T&& x)//x可以接收任意类型
	:_next(nullptr)
    ,_prev(nullptr)
    ,_data(std::forward<T>(x))
{}

3、左值引用和右值引用的使用场景和意义

3.1左值引用的使用场景

左值引用在函数传参、函数传返回值(必须保证返回值出了作用域还在)时使用可以减少拷贝。如果函数的返回值出了作用域会被销毁,则不能使用左值引用来减少拷贝(销毁后引用的对象非法),这个时候就需要使用右值引用了。C++在没有右值引用的时候,可以采用输出型参数的方法解决传值返回多次拷贝的问题。

3.2右值引用的使用场景

使用场景一:深拷贝的类中的传值返回的拷贝问题

C++11通过右值引用实现的移动构造和移动赋值解决值返回多次拷贝的问题,提升了效率:

class string
{
public:
    //拷贝构造
    string(const string& s)//传入的s是左值,需要老老实实构造
    {
        string tmp(s.c_str());
        swap(tmp);
    }
    //移动构造
    string(string&& s)//传入的s是将亡值,可以换走s的成员
    {
        swap(s);//将s的成员直接换给*this,s消亡后自动调用析构函数
    }
	// 赋值重载
    string& operator=(const string& s)
    {
        string tmp(s);
        swap(tmp);
        return *this;
    }
	// 移动赋值
    string& operator=(string&& s)
    {
        swap(s);
        return *this;
    }
private:
    char* _str = nullptr;
    size_t _capacity = 0;
    size_t _size = 0;
};

对于深拷贝的类,C++11使用右值引用实现的移动构造和移动赋值,在需要拷贝的场景中,可以直接转移将亡值的资源。如下图,虽然to_string是传值返回,但是str被编译器识别为将亡值,编译器会调用移动构造一步到位的对ret1进行构造,代价很低。

【送书】【C++11】左值引用和右值引用

使用场景二:插入右值数据,也可以减少拷贝

int main()
{
	list<string> it;
	string s1("1111");
	it.push_back(s1);//左值,深拷贝
	it.push_back(string("2222"));//右值,直接移动构造转移右值资源
	it.push_back("3333");//右值,直接移动构造转移右值资源
	return 0;
}

三、《Git从入门到精通》 

【送书】【C++11】左值引用和右值引用

【内容简介】 

        Git是一款让人一开始觉得很容易学,但却很难精通的工具。本书除了介绍Git的相关知识外,还会模拟各种常见的状况,让读者知道应该在什么时候使用什么指令。
      《Git从入门到精通》共分11个章节,1~3章介绍安装工具及环境,对于已经安装完成的读者可直接从第4章开始阅读。第5章介绍Git基本的使用方式,虽然难度不高,但却是整个Git系统的基础。第6章介绍Git中常用的分支功能以及使用情境,第7~9章则是介绍如何修改现有的历史记录、使用标签,以及如何应对其他常见的状况。
        前面的内容都是在自己的计算机上就可以完成的,从第10章开始介绍如何将自己计算机里的记录推一份到线上(GitHub)。*后一章(第11章)介绍团队开发时可能会使用的开发过程Git Flow。
        市面上的参考书籍或网络教程大多是教大家如何通过终端机指令来学习Git,这让不少想学习Git的新手打了退堂鼓。本书除了教大家如何在终端机视窗中输入Git指令,还搭配了图形界面工具,缓和了读者的学习曲线,让读者更容易上手。

京东自营购买链接:

《Git从入门到精通》(高见龙)【摘要 书评 试读】- 京东图书

 送书活动
本期书籍为《Git从入门到精通》送一本 
开奖时间:2023-04-09-23:59
参与方式:
1.点赞收藏文章
2.在评论区留言:人生苦短,我用Git(留言最多五条)
3.抽奖方式为评论区留言随机抽奖(C语言rand()函数随机抽取),会在评论区如期公布中奖者,包邮到家。

🍓 获奖名单🍓

 

zerodreamer(已私信,因三日未回复故重抽)

EnticE152(重抽中奖)文章来源地址https://www.toymoban.com/news/detail-408369.html

到了这里,关于【送书】【C++11】左值引用和右值引用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [开发语言][c++]:左值、右值、左值引用、右值引用和std::move()

    写在前面: 如果你也被 左值、右值、左值引用、右值引用和std::move 搞得焦头烂额,相关概念和理解不够深入,或者认识模棱两可,那么这篇文章将非常的适合你,耐心阅读,相信一定会有所收获~~ 左值: 可以取地址、位于等号左边 – 表达式结束后依然存在的持久对象

    2024年02月02日
    浏览(51)
  • MordernC++之左值(引用)与右值(引用)

    C++中左值与右值的概念是从C中继承而来,一种简单的定义是 左值能够出现再表达式的左边或者右边,而右值只能出现在表达式的右边 。 另一种区分左值和右值的方法是: 有名字、能取地址的值是左值,没有名字、不能取地址的值是右值 。比如上述语句中a,b, c是变量可以

    2023年04月09日
    浏览(30)
  • 初识C++之左值引用与右值引用

    目录 一、左值引用与右值引用 1. 左值和右值的概念 1.1 左值 1.2 右值  1.3 左值与右值的区分 2. 左值引用与右值引用 2.1 左值引用与右值引用的使用方法 2.2 左值引用的可引用范围 2.3 右值引用的可引用范围 3. 右值引用的作用 3.1 减少传值返回的拷贝 3.2 插入时的右值引用 4

    2023年04月26日
    浏览(28)
  • 左值引用、右值引用,std::move() 的汇编解释

    1:左值引用 引用其实还是指针,但回避了指针这个名字。由编译器完成从地址中取值。以vs2019反汇编: 如图,指针和引用的汇编代码完全一样。但引用在高级语言层面更友好,对人脑。比如可以少写一个 * 号和 - 。 ,以下是指针和引用的使用: 以上就是左值引用,引用的

    2024年02月04日
    浏览(28)
  • C++ 学习系列 1 -- 左值、右值与万能引用

    简单的说,左值可以放在等号的左边,右值可以放在等号的右边。 左值可以取地址,右值不能取地址。 1.1 左值举例: 变量、函数或数据成员 返回左值引用的表达式 如 ++x、x = 1、cout \\\' \\\'  int x = 0 1.2 右值举例: 返回非引用类型的表达式 如 x++、x + 1 除字符串字面量之外的字面

    2024年02月14日
    浏览(32)
  • C++右值引用(左值表达式、右值表达式)(移动语义、完美转发(右值引用+std::forward))(有问题悬而未决)

    在 C++ 中,表达式可以分为左值表达式和右值表达式。左值表达式指的是可以出现在赋值语句左边的表达式,例如变量、数组元素、结构体成员等;右值表达式指的是不能出现在赋值语句左边的表达式,例如常量、临时对象、函数返回值等。 右值是指将要被销毁的临时对象或

    2024年02月04日
    浏览(33)
  • 【C++】C++11右值引用

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.什么是左值什么是右值 左值 右值 2.什么是左值引用什么是右值引用 左

    2024年04月22日
    浏览(38)
  • 【C++学习】C++11——新特性 | 右值引用 | 完美转发

    🐱作者:一只大喵咪1201 🐱专栏:《C++学习》 🔥格言: 你只管努力,剩下的交给时间! C++的发展截至到目前为止,虽然版本有很多,但是C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一

    2024年02月06日
    浏览(26)
  • 【C++】—— C++11新特性之 “右值引用和移动语义”

    前言: 本期,我们将要的介绍有关 C++右值引用 的相关知识。对于本期知识内容,大家是必须要能够掌握的,在面试中是属于重点考察对象。 目录 (一)左值引用和右值引用 1、什么是左值?什么是左值引用? 2、什么是右值?什么是右值引用? (二)左值引用与右值引用比

    2024年02月11日
    浏览(28)
  • C++11『右值引用 ‖ 完美转发 ‖ 新增类功能 ‖ 可变参数模板』

    ✨个人主页: 北 海 🎉所属专栏: C++修行之路 🎃操作环境: Visual Studio 2022 版本 17.6.5 自从C++98以来,C++11无疑是一个相当成功的版本更新。它引入了许多重要的语言特性和标准库增强,为C++编程带来了重大的改进和便利。C++11的发布标志着C++语言的现代化和进步,为程序员

    2024年02月05日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包