c++11的一些新特性

c++11

  • 1. {}初始化
  • 2. 范围for循环
  • 3. final与override
  • 4. 右值引用
    • 4.1 左值引用和右值引用
    • 4.2 左值引用与右值引用比较
  • 5. lambda表达式
  • 6. 声明
    • 6.1 auto
    • 6.2 decltype
    • 6.3 nullptr
  • 7. 可变参数模版

1. {}初始化

在C++中,使用花括号初始化的方式被称为列表初始化。列表初始化可以用于数组、结构体、类等类型的初始化。在C++11之前,列表初始化仅能用于数组和POD类型的初始化。C++11新标准将列表初始化应用于所有对象的初始化。以下是一些使用列表初始化的例子:

struct Point 
{int _x;int _y;
}; class foo 
{
public:foo(int i, double d) :_i(i), _d(d) {} // 构造函数
private:int _i;double _d;
};
int main()
{int arr[]{ 1, 2, 3, 4, 5 }; // 数组Point p{ 1,2 }; // 结构体foo f{ 1, 3.14 }; // 类return 0;
}

以上代码中,arr 是一个整型数组,使用列表初始化方式进行了初始化;p 是一个结构体,使用列表初始化方式对其成员变量进行了初始化;f 是一个类对象,使用列表初始化方式对其成员变量进行了初始化。

2. 范围for循环

在C++中,范围for循环是一种用于遍历数组、容器、初始化列表等类型的语法结构。它的语法格式如下:

for (declaration : expression)
{// 循环体
}

其中,declaration 表示遍历声明,在遍历过程中,当前被遍历到的元素会被存储到声明的变量中。expression 是要遍历的对象,它可以是表达式、容器、数组、初始化列表等。

以下是一个使用范围for循环的例子:

#include <iostream>
#include <vector>int main()
{std::vector<int> v = {1, 2, 3, 4, 5};for (auto value : v){std::cout << value << " ";}std::cout << std::endl;return 0;
}

以上代码中,v 是一个整型向量,使用范围for循环方式进行了遍历。
需要注意的是,在使用范围for循环遍历容器时,循环会自动以容器为范围展开,并且循环中也屏蔽掉了迭代器的遍历细节,直接抽取容器中的元素进行运算,使用这种方式进行循环遍历会让编码和维护变得更加简便。

其中还有一个点需要注意,上述value相当于一个形参,也就是说value改变,不影响数组v的改变,那么怎么在遍历的时候又能修改数组v?其实可以使用引用访问元素,如下:

#include <iostream>
#include <vector>int main()
{std::vector<int> v = { 1, 2, 3, 4, 5 };cout << "没有使用引用访问:";for (auto value : v){value *= 2;}for (auto value : v){std::cout << value << " ";}std::cout << std::endl;cout << "使用引用访问:";for (auto &value : v){value *= 2;}for (auto value : v){std::cout << value << " ";}std::cout << std::endl;return 0;
}

在这里插入图片描述
在C++中,使用范围for循环时,如果使用引用访问元素,可以避免对元素进行拷贝,从而提高程序的效率。当使用值访问元素时,会对元素进行一次拷贝,而使用引用访问元素时,则不会进行拷贝。因此,在不改变元素的情况下,使用引用访问元素可以减少一次拷贝,提高程序的效率。

3. final与override

在C++11中,override 和 final 是两个新的关键字,用于增强代码的安全性和可读性。

override 用于在派生类中重写基类的虚函数时,显式地告诉编译器此函数是重写基类的虚函数。如果重写时函数名、参数列表和返回类型都和基类的虚函数一致,但是没有加上 override 关键字,那么编译器无法判断是否是故意的重写,容易导致程序出错。加上 override 关键字后,编译器会在编译时检查是否真的重写了基类的虚函数,如果没有则会报错,从而避免了这种错误。

final 用于修饰类、函数或者变量,表示它们是终态的,不能被派生类、重写或者修改。使用 final 关键字可以防止子类再覆写父类的虚函数。如果一个虚函数被声明为 final,则派生类不能再重写它。

4. 右值引用

4.1 左值引用和右值引用

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

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;
}

什么是右值?什么是右值引用?
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名。

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;
}

需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用。

4.2 左值引用与右值引用比较

  1. 左值引用是用符号 & 声明的,它只能绑定到左值,即可以取地址、有名字、非临时的对象。左值引用可以用来修改或读取所绑定的对象的值。
  2. 右值引用是用符号 && 声明的,它只能绑定到右值,即不能取地址、没有名字、临时的对象。右值引用可以用来延长所绑定的对象的生命周期,或者实现移动语义,即将对象的资源从一个所有者转移到另一个所有者,而不需要进行拷贝。
  3. 一个例外是,const左值引用可以绑定到右值,这样可以实现对右值的只读访问,而不改变其生命周期。
  4. 另一个例外是,在函数重载时,如果有一个参数既可以接受左值引用,又可以接受右值引用,那么编译器会优先选择左值引用。这是为了避免对左值进行不必要的移动操作。

左值引用和右值引用的优缺点如下:

  1. 左值引用的优点是可以对所引用的对象进行修改或读取,而不需要拷贝或移动。左值引用的缺点是不能绑定到右值,如果需要绑定到右值,必须使用常量左值引用,但这样就不能修改所引用的对象了。
  2. 右值引用的优点是可以实现移动语义,减少拷贝或赋值操作的开销,提高程序的效率。右值引用的缺点是不能修改所引用的对象,而且会改变所引用对象的状态,使其失去资源的所有权。

5. lambda表达式

在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法,但是如果排序的是自定义类型元素,每次为了实现一个algorithm算法,都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式。

在C++11中,Lambda表达式是一种用于定义匿名函数的语法结构。Lambda表达式可以用于任何需要函数对象的地方,例如函数参数、返回值、STL算法等。Lambda表达式的语法格式如下:

[capture-list] (parameters) mutable -> return-type { statement };

lambda表达式各部分说明:

  1. [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
  2. (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略。
  3. mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  4. ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
  5. {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

注意:
在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

int main()
{// 最简单的lambda表达式, 该lambda表达式没有任何意义[] {};// 省略参数列表和返回值类型,返回值类型由编译器推导为intint a = 3, b = 4;[=] {return a + 3; };// 省略了返回值类型,无返回值类型auto fun1 = [&](int c) {b = a + c; };fun1(10);cout << a << " " << b << endl;// 各部分都很完善的lambda函数auto fun2 = [=, &b](int c)->int {return b += a + c; };cout << fun2(10) << endl;// 复制捕捉xint x = 10;auto add_x = [x](int a) mutable { x *= 2; return a + x; };cout << add_x(10) << endl;return 0;
}int main()
{int x = 10, y = 20;auto func1 = [](int x = 1,int y = 2) //当捕捉列表和参数列表都有x,y,优先用参数列表中的值。{cout << x + y << endl; // 3};func1();return 0;
}int main()
{int x = 0, y = 1;int m = 0, n = 1;auto swap1 = [](int& rx, int& ry){int tmp = rx;rx = ry;ry = tmp;};swap1(x, y);cout << x << " "<< y << endl;// 引用捕捉auto swap2 = [&x, &y](){int tmp = x;x = y;y = tmp;};swap2();cout << x << " " << y << endl;// 混合捕捉auto func1 = [&x, y](){//...};// 全部引用捕捉auto func2 = [&](){//...};// 全部传值捕捉auto func3 = [=](){//...};// 全部引用捕捉,x传值捕捉auto func4 = [&, x](){//...};return 0;
}

lambda表达式的优点是可以使代码更加简洁紧凑,并且可以避免定义不必要的函数对象。Lambda表达式的缺点是可能会降低代码的可读性和可维护性。

6. 声明

6.1 auto

auto是C++11引入的一个关键字,用于在声明变量时自动推导变量的类型。auto的使用可以让编译器在编译期间自动推算出变量的类型,这样就可以更加方便的编写代码了。auto还可以用于定义函数返回值类型,但此时auto仍然使用的是模板实参推断的机制,因此返回类型为auto的函数如果返回一个初始化列表,则会出错。

6.2 decltype

在C++11中,decltype 是一种用于推导表达式类型的关键字。decltype 可以用于推导变量、函数返回值、表达式等的类型。decltype 的语法格式如下:

decltype(expression)

其中,expression 是要推导类型的表达式。

以下是一个使用 decltype 的例子:

#include <iostream>int main()
{int i = 42;decltype(i) j = i + 1;std::cout << "i = " << i << ", j = " << j << std::endl;return 0;
}

以上代码中,使用了 decltype 推导了变量 j 的类型。

decltype 的优点是可以在编译期间推导出表达式的类型,从而提高程序的效率。decltype 的缺点是可能会降低代码的可读性和可维护性。

6.3 nullptr

C++11中,nullptr是一个用于表示空指针的关键字,它可以替代C++03中的0或NULL。nullptr的类型是std::nullptr_t,它可以隐式转换为任意类型的指针或成员指针,但不能转换为整数类型或布尔类型。nullptr的优点是可以避免一些类型推导的歧义,例如在函数重载或模板参数推导时。nullptr的缺点是可能会与一些旧代码不兼容,例如使用NULL作为整数常量的代码。

在C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

7. 可变参数模版

在C++11中,可变参数模板是一种用于定义可变数量参数的模板。它允许模板函数或类接受任意数量的参数,包括类型、非类型和模板参数。可变参数模板的语法格式如下:

template<typename... Args>
void foo(Args... args)
{// 函数体
}

其中,Args 是一个模板参数包,可以接受任意数量的模板参数。在函数体中,可以使用 args… 来展开参数包,以便对每个参数进行操作。

可变参数模版中有一点需要注意,在使用sizeof()求可变参数的个数时,应该这样书写:sizeof…(args),//错误格式sizeof(args…);如下所示:

template <class ...Args>
void ShowList(Args... args)
{cout << sizeof...(args) << endl; //求可变参数的个数
}
int main()
{ShowList(1);ShowList(1, 2.2);ShowList(1, 2.2, "hello");return 0;
}

在这里插入图片描述

如何解析可变参数包?这里使用递归来解决。以下是一个使用可变参数模板的例子:

void ShowList() //函数重载,当参数个数为0时,没有该函数,就会找不到匹配的函数
{cout << endl;
}
template <class T, class ...Args>
void ShowList(const T& val, Args... args) //每次从参数包中解析一个
{cout << val << " ";ShowList(args...);
}
int main()
{ShowList(1);ShowList(1, 2.2);ShowList(1, 2.2, "three");return 0;
}

在这里插入图片描述

可变参数模板的优点是可以使代码更加灵活和通用,可以接受任意数量和类型的参数。可变参数模板的缺点是可能会降低代码的可读性和可维护性。

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

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

相关文章

让NPU跑起来迅为RK3588开发板设置交叉编译器

让NPU跑起来迅为RK3588开发板设置交叉编译器 编译器下载地址是网盘资料“iTOP-3588 开发板\02_【iTOP-RK3588 开发板】开发资料 \12_NPU 使用配套资料\03_编译所需工具\Linux”。 拷贝 gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.gz 到 Ubuntu 的/opt/tool_ch…

记录crack某IDE插件过程

声明&#xff1a;本文仅记录学习过程&#xff0c;已对关键位置脱敏处理&#xff0c;未提供任何工具&#xff0c;请支持正版。 反编译jar包 使用cfr进行对插件核心jar包MyBxxxxxx-obfuss.jar进行反编译&#xff0c;在本地生成a.txt。 java -jar cfr-0.152.jar MyBxxxx-obfuss.…

外包干了2个月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

MATLAB入门-字符串操作

MATLAB入门-字符串操作 注&#xff1a;本篇文章是学习笔记&#xff0c;课程链接是&#xff1a;link MATLAB中的字符串特性&#xff1a; 无论是字符还是字符串&#xff0c;都要使用单引号来‘’表示&#xff1b;在MATLAB中&#xff0c;字符都是在矩阵中存储的&#xff0c;无论…

【GO语言基础】变量常量

系列文章目录 【Go语言学习】ide安装与配置 【GO语言基础】前言 【GO语言基础】变量常量 【GO语言基础】数据类型 文章目录 系列文章目录常量和枚举变量声明全局变量声明大小写敏感 总结 常量和枚举 使用const关键字声明常量&#xff0c;并为每个常量提供显式的值。Go语言没有…

算法训练营day48|动态规划 part09:打家劫舍(LeetCode 198.打家劫舍、213.打家劫舍II、337.打家劫舍 III)

文章目录 198.打家劫舍思路分析代码实现思考总结 213.打家劫舍II思路分析代码实现 337.打家劫舍 III (树形DP)思路分析代码实现思考总结 198.打家劫舍 题目链接&#x1f525;&#x1f525; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#…

二维码智慧门牌管理系统:数据现势性,满足应用需求的根本保证

文章目录 前言一、项目背景二、数据的现势性三、系统的优势四、应用前景 前言 在当今信息化社会&#xff0c;数据的重要性日益凸显&#xff0c;尤其是数据的现势性&#xff0c;它决定着服务的质量和满足应用需求的能力。近日&#xff0c;一个创新的二维码智慧门牌管理系统项目…

033:跨域,vue端和 Nignx反向代理的配置详细解析

第033个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

IEC 61850扫盲

目录 1 简介 2 主要特点 2.1 信息分层 2.2 信息模型与通信协议独立 2.3 数据自描述 2.4 面向对象数据统一建模 2.5 带确认服务 2.6 不带确认的服务 2.7 VMD&#xff08;虚拟制造设备&#xff09; 2.8 GOOSE&#xff08;Generic Object Oriented Substation Event&…

Vue.js的服务器端渲染(SSR):为什么和如何

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【C# Programming】继承、接口

一、继承 1、派生 继承在相似而又不同的概念之间建立了类层次概念。 更一般的类称为基类&#xff0c;更具体的类称为派生类。派生类继承了基类的所有性质。 定义派生类要在类标识符后面添加一个冒号&#xff0c;接着添加基类名。 public class PdaItem {public string Name {…

时序预测 | MATLAB实现ARMA自回归移动平均模型时间序列预测

时序预测 | MATLAB实现ARMA自回归移动平均模型时间序列预测 目录 时序预测 | MATLAB实现ARMA自回归移动平均模型时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现ARMA时间序列预测&#xff08;完整源码和数据&#xff09; 本程序基于MATLAB的armax函…

安全实战 | 怎么用零信任防范弱密码?

防范弱密码&#xff0c;不仅需要提升安全性&#xff0c;更需要提升用户体验。 比如在登录各类业务系统时&#xff0c;我们希望员工登录不同系统不再频繁切换账号密码&#xff0c;不再需要3-5个月更换一次密码&#xff0c;也不再需要频繁的输入、记录、找回密码。 员工所有的办…

JDK9特性——模块化REPL工具

文章目录 前言模块化模块化案例 可交互的REPL工具 前言 谈到Java9大家往往第一个想到的就是Jigsaw项目&#xff08;后改名为Modularity&#xff09;。众所周知&#xff0c;Java已经发展超过20年(95年最初发布)&#xff0c;Java和相关生态在不断丰富的同时也越来越暴露出一些问…

开源药店商城系统源码比较:哪个适合你的药品电商业务

在构建药品电商业务时&#xff0c;选择适合的药店商城系统源码是至关重要的决策之一。开源药店商城系统源码提供了快速入门的机会&#xff0c;但在选择之前&#xff0c;您需要仔细考虑您的需求、技术要求和可扩展性。本文将比较几个流行的开源药店商城系统源码&#xff0c;以帮…

照片批量处理 7000张

需求&#xff1a; 有6700照片导入系统&#xff1b; 系统只支持500张/每次&#xff1b; 6700 按机构分类复制提取出来&#xff1b; 分批次导入&#xff1b; 6700 分17份复制到对应文件夹中&#xff1b; 照片按照学号命名的&#xff1b; 20231715401.jpg 开始用bat脚本…

Chatbase:AI客服聊天机器人工具

【产品介绍】 名称 Chatbase.co 具体描述 Chatbase.co 是一个智能的聊天机器人平台&#xff0c;它可以帮助用户快速地构建、部署和分析用户的聊天机器人&#xff0c;无论 用户是一个初学者还是一个专家。用户可以使用 Chatbase.co …

C# 查找迷宫路径

1.导入图像&#xff0c;并且将图像转灰度 using var img new Image<Bgr, byte>(_path); using var grayImg img.Convert<Gray, byte>(); 2.自动二值化图像 using var inputGrayOut new Image<Gray, byte>(grayImg.Size); // 计算OTSU阈值 var threshol…

技师学院物联网实训室建建设方案

一、概述 1.1专业背景 物联网&#xff08;Internet of Things&#xff09;被称为继计算机、互联网之后世界信息产业第三次浪潮&#xff0c;它并非一个全新的技术领域&#xff0c;而是现代信息技术发展到一定阶段后出现的一种聚合性应用与技术提升&#xff0c;是随着传感网、通…

Echarts 旭日图的详细配置过程

文章目录 旭日图 简介配置过程简易示例 旭日图 简介 Echarts旭日图是一种数据可视化图表类型&#xff0c;用于展示层次关系数据的分布情况。旭日图通过不同的环形区域和扇形区域来表示数据的层次和大小关系&#xff0c;从而形成一个太阳的形状&#xff0c;因此得名旭日图。 E…