C++11新特性系列(一)

目录

1、C++11简介

2、列表的初始化

2.1 {}初始化

2.2 initializer_list

3、auto与decltype

3.1 auto

3.2 decltype

4、范围for循环

5、右值引用和移动语义

4.1 左值引用和右值引用

4.1.1 左值引用

4.1.2 右值引用

4.2 右值引用使用场景和意义


1、C++11简介

        C++11是C++语言的一个重要版本,于2011年发布。它引入了许多新特性和改进,以提高C++语言的表达能力、可移植性和性能。相比于 C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中 约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言, C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率。

2、列表的初始化

2.1 {}初始化

C++98,允许{}对数组和结构体元素进行初始化

//在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。
struct A
{int a = 0;int b = 0;
};
int main()
{int a[] = { 1,2,3,4,5,6 };A a={ 1,2 };return 0;
}

 C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自 定义的类型,使用初始化列表时,可添加等号(=),也可不添加

//在C++11中,扩大了用大括号括起的列表(初始化列表)的使用范围,
// 使其可用于所有的内置类型和用户自定义的类型
//使用初始化列表时,可添加等号(= ),也可不添加。template<class T>
struct A
{T a;T b;
};int main()
{A<int> a{1,2};int b{ 0 };return 0;
}
并且适用于new表达式的初始化
创建对象时也可以使用列表初始化方式调用构造函数初始化
//创建对象时也可以使用列表初始化方式调用构造函数初始化
template<class T>
class Example
{
public:Example(T a,T b):_a(a),_b(b){}
private:int _a;int _b;
};
int main()
{Example<int> a{ 1,2 };Example<double> a={ 1.2,2.5 };return 0;
}

2.2 initializer_list

        此类型用于访问 C++ 初始化列表中的值,该列表是 const T 类型的元素列表。此类型的对象由编译器根据初始化列表声明自动构造,该声明是用大括号括起来的逗号分隔元素的列表。

std::initializer_list 一般是作为构造函数的参数,
C++11STL 中的不少容器就增std::initializer_list作为参数的构造函数。
这样初始化容器对象就更方便了。也可以作为 operator= 的参数,这样就可以用大括号赋值
在list中就增加了initializer_list的构造
vector,map,中同样增加了initializer_list构造
map
我们之前模拟实现过vector,那么我们可以尝试为vector加上initializer_list构造
		vector(initializer_list<T> l){_start = new T[l.size()];_finish = _start + l.size();_endofstorage = _start + l.size();iterator it = _start;typename initializer_list<T>::iterator it1 = l.begin();while (it1 != l.end()){*it++ = *it1++;}}vector<T>& operator=(initializer_list<T> l){//调用构造vector<T> tmp(l);std::swap(_start, tmp._start);std::swap(_finish, tmp._finish);std::swap(_endofstorage, tmp._endofstorage);return *this;}

3、auto与decltype

3.1 auto

        在C++98 auto 是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto 就没什么价值了。 C++11 中废弃 auto 原来的用法,将 其用于实现自动类型腿断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初
始化值的类型。
#include<map>
int main()
{auto pf = strcpy;cout << typeid(pf).name() << endl;int i = 10;auto p = &i;cout << typeid(p).name() << endl;map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };//map<string, string>::iterator it = dict.begin();auto it = dict.begin();   //自动类型推断return 0;
}

3.2 decltype

关键字 decltype 将变量的类型声明为表达式指定的类型。
decltype是 C++11 引入的一个关键字,用于推导表达式的类型并生成对应的类型声明。它的语法形式为:
decltype(expression) variable_name;

其中 expression 是一个表达式,variable_name 是待声明的变量名。decltype 将根据 expression 推导出 variable_name 的类型。

4、范围for循环

C++11引入了范围(range-based)for循环,它提供了一种简洁的方式来遍历容器(比如数组、向量、列表等)中的元素,其语法如下所示:

for (element : container)
{// 执行操作
}

其中,element 是容器中每个元素的临时变量,container 是要遍历的容器。在每次循环迭代中,element 都会被赋值为容器中的一个元素,直到遍历完整个容器。

范围for循环可以用于大多数标准容器,包括向量、列表、集合、映射等。如果你希望在遍历过程中修改容器中的元素,则应该使用引用类型的变量作为循环变量,如下所示:

#include <iostream>
#include <vector>int main()
{std::vector<int> numbers = {1, 2, 3, 4, 5};// 使用范围for循环修改整型数组中的元素for (int &num : numbers){num *= 2;}// 输出修改后的数组for (int num : numbers){std::cout << num << " ";}return 0;
}

5、右值引用和移动语义

4.1 左值引用和右值引用

在C++中,引用是一个非常重要的概念,它们允许我们在不复制对象的情况下访问对象。C++11引入了左值引用(lvalue reference)和右值引用(rvalue reference)的概念,它们都是引用的一种形式,但它们有不同的使用方式和语义。

4.1.1 左值引用

左值引用绑定到左值(lvalue),即可以取地址的表达式,例如变量、对象成员或返回左值的函数调用。左值引用用于引用可以修改的对象,常见的情况包括函数参数传递和赋值操作符的重载。左值引用使用 & 符号声明。

int x = 5; int& ref = x; // ref 是 x 的左值引用

什么是左值?什么是左值引用?
左值是一个表示数据的表达式 ( 如变量名或解引用的指针 ) 我们可以获取它的地址+可以对它赋
值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边 定义时 const 修饰符后的左
值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。

int main()
{//左值int* ptr = new int[10]{ 0 };int a = 10;const int  c = 20;//左值引用int*& pp = ptr;int& d = a;//定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。//c = 3;   不能赋值const int& rc = c;int& pvalue = *ptr;return 0;
}

4.1.2 右值引用

右值引用绑定到右值(rvalue),即临时对象或表达式的结果。右值引用通常用于移动语义和完美转发,它们允许我们有效地转移资源的所有权或延长临时对象的生命周期。右值引用使用 && 符号声明。

int&& rref = 10; // rref 是 10 的右值引用

什么是右值?什么是右值引用?
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值 ( 这个不能是左值引
用返回 ) 等等, 右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能
取地址 右值引用就是对右值的引用,给右值取别名。
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可
以取到该位置的地址.
int main()
{int x = 1;int y = 2;//以下是常见的右值10;x + y;//右值引用int&& r1 = x + y;int&& r2 = 10;//不能取字面量10的地址,但是r2引用后,可以对r2取地址,也可以修改r2。r2 = 20;//如果不想r2被修改,可以用const int&& r2 去引用//const int&& r2 = 10;return 0;
}
左值引用总结:
1. 左值引用只能引用左值,不能引用右值。
2. 但是 const 左值引用既可引用左值,也可引用右值。
右值引用总结:
1. 右值引用只能右值,不能引用左值。
2. 但是右值引用可以 move 以后的左值。
int y = 2;
int&& r3 = move(y);

4.2 右值引用使用场景和意义

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
namespace stringtest
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){//cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造string(const string& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;string tmp(s._str);swap(tmp);}// 赋值重载string& operator=(const string& s){cout << "string& operator=(string s) -- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}// 移动构造string(string&& s):_str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 移动语义" << endl;swap(s);}// 移动赋值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 移动语义" << endl;swap(s);return *this;}~string(){delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}string operator+=(char ch)//string& operator+=(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}private:char* _str;size_t _size;size_t _capacity; // 不包含最后做标识的\0};
}void func(stringtest::string s1)
{}
void func2(const stringtest::string& s)
{}int main()
{stringtest::string s1("hello world");func(s1);func2(s1);//左值引用减少了拷贝//string operator+=(char ch)s1 += 'h';return 0;
}

左值引用的短板:

但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,只能传值返回。string to_string(int value) 函数中可以看到,这里只能使用传值返回,传值返回会导致至少1 次拷贝构造 ( 如果是一些旧一点的编译器可能是两次拷贝构造 )
右值引用和移动语义解决上述问题:
增加移动构造, 移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不
用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己

 

namespace stringtest
{stringtest::string to_string(int value){bool flag = true;if (value < 0){flag = false;value = 0 - value;}stringtest::string str;while (value > 0){int x = value % 10;value /= 10;str += ('0' + x);}if (flag == false){str += '-';}std::reverse(str.begin(), str.end());return str;}
}int main()
{stringtest::string s1 = stringtest::to_string(1235433);return 0;
}

通过观察

移动构造本质是将参数右值的资源窃取过来,占位已有。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821585.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高通 Android 12 源码编译aidl接口

最近在封装系统sdk接口 于是每次需要更新aidl接口 &#xff0c;传统方式一般使用make update-api或者修改Android.mk文件&#xff0c;今天我尝试使用Android.bp修改 &#xff0c;Android 10之前在Android.mk文件修改&#xff0c;这里不做赘述。下面开始尝试修改&#xff0c;其实…

InnoDB架构:磁盘篇

InnoDB架构&#xff1a;磁盘篇 InnoDB是MySQL数据库中默认的存储引擎&#xff0c;它为数据库提供了事务安全型&#xff08;ACID兼容&#xff09;、行级锁定和外键支持等功能。InnoDB的架构设计优化了对于读取密集和写入密集型应用的性能表现&#xff0c;是一个高度优化的存储系…

近屿智能全新推出AI培训产品:AIGC大模型工程师与产品经理学习路径图

如今&#xff0c;人工智能和自然语言处理技术的发展&#xff0c;使得AI生成的内容&#xff08;AIGC&#xff0c;AI Generated Content&#xff09;领域开发出了巨大的潜力。就像业内巨头OpenAI公司&#xff0c;开发出了一系列自然语言处理模型ChatGPT&#xff0c;不仅带动了全世…

C语言单向链表的经典算法

1.分割链表 2.移除链表元素 3.反转链表 4.合并两个有序链表 5.链表的中间结点 6.环形链表的约瑟夫问题 1.分割链表: 1.思路&#xff1a;创建新链表&#xff0c;小链表和大链表。如图 代码如下 /*** Definition for singly-linked list.* struct ListNode {* int val…

Unity类银河恶魔城学习记录12-18,19 p140 Options UI-p141 Finalising ToolTip源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_ToolTip.cs using TMPro; using UnityEngine;public class UI_ToolTip :…

IBM SPSS Statistics for Mac中文激活版:强大的数据分析工具

IBM SPSS Statistics for Mac是一款功能强大的数据分析工具&#xff0c;为Mac用户提供了高效、精准的数据分析体验。 IBM SPSS Statistics for Mac中文激活版下载 该软件拥有丰富的统计分析功能&#xff0c;无论是描述性统计、推论性统计&#xff0c;还是高级的多元统计分析&am…

【面试经典 150 | 链表】K 个一组翻转链表

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;迭代 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

【从零开始手搓12306项目】第一阶段遇到的问题及解决方案

IDEA中datebase连接mysql失败 读取外包函数报错 注意区分private和public 找不到数据库&#xff1f; 一定要注意数据库的url链接&#xff0c;在datebase的url复制过来 xml和java对应不上&#xff1f; 最好复制一遍到xml文件 git忽略条件文件目录 定义Git全局的 .gitigno…

人工智能与IP代理池:解析网络数据采集的未来

前言 随着互联网的快速发展&#xff0c;数据成为了当今社会最宝贵的资源之一。然而&#xff0c;要获取大量的网络数据并进行有效的分析&#xff0c;往往需要面对诸多挑战&#xff0c;其中之一就是网络封锁与反爬虫机制。在这个背景下&#xff0c;人工智能&#xff08;AI&#x…

Python 物联网入门指南(七)

原文&#xff1a;zh.annas-archive.org/md5/4fe4273add75ed738e70f3d05e428b06 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第二十四章&#xff1a;基本开关 到目前为止一定是一段史诗般的旅程&#xff01;回想一下你开始阅读这本书的时候&#xff0c;你是否曾想象…

IP协议如何进行地址管理?

如今&#xff0c;IP协议有两个版本&#xff0c;分别是IPv4和IPv6&#xff0c;IPv4是目前主要应用的版本。IPv4的IP地址是以4个字节的数字来表示的&#xff0c;比如 127.0.0.1。因此&#xff0c;IPv4所能表示IP地址的个数是2^32次方&#xff0c;也就是42亿多个&#xff0c;看起来…

OpenStack 入门体验

目录 一、云计算概述 1.1、什么是云计算 1.2、云计算的服务模型 1&#xff09;IaaS 2&#xff09;PaaS 3&#xff09;SaaS 1.3、OpenStack 概述 1&#xff09;OpenStack 起源 2&#xff09;什么是 OpenStack 3&#xff09;OpenStack 优势 二、OpenStack 一…

RabbitMQ进阶学习

在之前的练习作业中&#xff0c;我们改造了余额支付功能&#xff0c;在支付成功后利用RabbitMQ通知交易服务&#xff0c;更新业务订单状态为已支付。 但是大家思考一下&#xff0c;如果这里MQ通知失败&#xff0c;支付服务中支付流水显示支付成功&#xff0c;而交易服务中的订…

IAM 统一身份认证与访问管理服务

即统一身份认证与访问管理服务&#xff0c;是云服务商提供的一套云上身份管理解决方案&#xff0c;可帮助企业安全地管理云上资源的访问权限。 在当今云计算时代&#xff0c;企业越来越依赖云服务来存储和处理敏感数据。然而&#xff0c;这也带来了新的安全挑战&#xff0c;即…

CentOS:执行make命令时报错g++: Command not found

报错截图&#xff1a; 其实很简单只需要安装一下 yum -y install gcc automake autoconf libtool make yum install gcc gcc-c

RabbitMQ交换机的类型

交换机类型 可以看到&#xff0c;在订阅模型中&#xff0c;多了一个exchange角色&#xff0c;而且过程略有变化&#xff1a; Publisher&#xff1a;生产者&#xff0c;不再发送消息到队列中&#xff0c;而是发给交换机 Exchange&#xff1a;交换机&#xff0c;一方面&#xff…

OSPF大型实验

OSPF大型实验 实验拓扑图 实验思路 1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两…

初识数据库与数据库管理系统

实体的概念与数据库 实体(对象): 客观存在的事物都是实体实体数据的存储要求: 必须按照一定的分类和规律存储数据库: 专门用于存储这些实体的信息的数据集合数据库的特点: 海量存储数据&#xff0f;数据检索非常方便保持数据信息的一致&#xff0f;完整&#xff0f;并实现数据…

通过 Ollama、Langchain 实现 RAG

RAG 是什么 RAG 在 Langchain 上的定义是&#xff0c;作为大语言模型最常用的场景就是问答系统&#xff0c;可以针对特别来源数据做问题回答&#xff0c;就是私有数据&#xff0c;这就是 RAG&#xff0c;英文全称是Retrieval Augmented Generation。就是对现有模型数据的增广&…

强化学习(二)马尔科夫决策过程 MDP

文章目录 1. 什么是马尔科夫过程2. 强化学习与MDP的关系3. 价值函数的贝尔曼方程3.1 状态价值函数的贝尔曼方程3.2 动作价值函数的贝尔曼方程3.3 价值函数递推关系的转换 4. 最优价值函数5. MDP计算最优值函数实例 1. 什么是马尔科夫过程 马尔科夫过程&#xff08;Markov Deci…