C++11新特性(二)

news2024/11/16 2:28:41

目录

 一、C++11的{}

1.初始化列表

2.initializer_list

二、可变参数模版

1.语法与原理

2.包扩展

3.empalce接口

三、新的类功能

四、lambda

1.语法

2.捕捉列表

3.原理

五、句装器

1.function

2.bind


 一、C++11的{}

1.初始化列表

  • C++11以后想统⼀初始化⽅式,试图实现⼀切对象皆可⽤{}初始化,{}初始化也叫做列表初始化
  • 关于c++11后的{}初始化,内置类型⽀持,⾃定义类型也⽀持。⾃定义类型使用{}初始化本质是类型转换,中间会产⽣临时对象,最后优化了以后变成直接构造。
  • {}初始化的过程中,可以省略掉=。
  • C++11列表初始化的本意是想实现⼀个⼤统⼀的初始化⽅式,其次他在有些场景下带来的不少便利,如容器push/inset多参数构造的对象时,{}初始化会很⽅便。

例如:

struct pt
{
    int x;
    int y;
}
int main()
{
	int a1 = { 7 };
	double d1 = { 26.3 };
	set<int> st1= { 71 };
    pt pos1={ 3, 4 };
	//......
	//=可省略
	int a2{ 7 };
	double d2{ 26.7 };
	set<int> st2{ 78 };
    pt pos2{ 3, 4 };
	//......
	return 0;
}

2.initializer_list

        上⾯的初始化已经很⽅便,但是对象容器初始化还是不太⽅便,⽐如⼀个vector对象,想⽤N个值去构造初始化,那么我们得实现很多个构造函数才能⽀持。

C++11库中提出了⼀个std::initializer_list的类

  • auto il = { 10, 20, 30 }; 这个类的本质是底层开⼀个数组,将数据拷⻉过来,std::initializer_list内部有两个指针分别指向数组的开始和结束。
  • std::initializer_list⽀持迭代器遍历。
  • 容器⽀持⼀个std::initializer_list的构造函数,也就⽀持任意多个值构成的 {x1,x2,x3...} 进⾏初始化。STL中的容器⽀持任意多个值构成的 {x1,x2,x3...} 进⾏初始化,就是通过std::initializer_list的构造函数⽀持的。

 例如:

int main()
{
	vector<int> arr{ 1,5,2,62,4 };
	unordered_map<char, int> mp{ {'a',1},{'p',8},{'v',8} };
	//可以任意传多个值,在此之前编译器是不能确定你要传入多少个值的,
	//所以底层用了std::initializer_list从而支持初始化多个值
	return 0;
}

二、可变参数模版

1.语法与原理

        C++11⽀持可变参数模板,也就是说⽀持可变数量参数的函数模板和类模板,可变数⽬的参数被称为参数包,存在两种参数包:模板参数包,表⽰零或多个模板参数;函数参数包:表⽰零或多个函数参数。

        也就是模板的参数个数是不确定的,当使用它的时候它会根据传入参数的个数自动去推导并生成对应的参数个数的函数或类。

template <class... Args> void Func(Args... x) {}
template <class... Args> void Func(Args&... x) {}
template <class... Args> void Func(Args&&... x) {}

        我们⽤省略号来指出⼀个模板参数或函数参数的表⽰⼀个包,在模板参数列表中,class...或
typename...指出接下来的参数表⽰零或多个类型列表;在函数参数列表中,类型名后⾯跟...指出
接下来表⽰零或多个形参对象列表;函数参数包可以⽤左值引⽤或右值引⽤表⽰,跟前⾯普通模板
⼀样,每个参数实例化时遵循引⽤折叠规则。
        可变参数模板的原理跟模板类似,本质还是去实例化对应类型和个数的多个函数。
这⾥我们可以使⽤sizeof...运算符去计算参数包中参数的个数。

2.包扩展

        包扩展就是一个将包里的元素取出来的操作,因为考虑到很多因数,在这个取这些元素过程会比较复杂。

        注意:包扩展是在编译时完成的。

如下一个包开展过程:

bf9f1c1df1c24ad48d19408dbcff7551.png

3.empalce接口

        C++11以后STL容器新增了empalce系列的接⼝,empalce系列的接⼝均为模板可变参数,功能上兼容push和insert系列,但是empalce还⽀持新玩法,假设容器为container<T>,empalce还⽀持直接插⼊构造T对象的参数,这样有些场景会更⾼效⼀些,可以直接在容器空间上构造T对象。
 

三、新的类功能

        在原来C++类中6个默认成员函数:构造函数、析构函数、拷⻉构造函数、拷⻉赋值重载、取地址重载、const取地址重载的基础上C++11新增了2个默认成员函数,移动构造函数移动赋值运算符重载

关键字功能:

  • default:强行生成默认成员函数。只需在需要编译器生成的默认成员函数声明加上=default即可。如下:
    class student
    {
    public:
    	student(const string& s, const int& num)
    		:_name(s),_age(num){}
    	student() = default;
    	~student() = default;
    private:
    	string _name;
    	int _age;
    };
  • delete:如果能想要限制某些默认函数的⽣成,在C++98中,是该函数设置成private,并且只声明补丁已,这样只要其他⼈想要调⽤就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指⽰编译器不⽣成对应函数的默认版本,称=delete修饰的函数为删除函数。例如:
    class student
    {
    public:
    	student(const string& s, const int& num) = delete;
    private:
    	string _name;
    	int _age;
    };
  • final:(1).防止类被继承。(2).防止函数被重写。
  • override:检查函数重写是否正确。

四、lambda

1.语法

        lambda 表达式本质是⼀个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。
        lambda 表达式语法使⽤层⽽⾔没有类型,所以我们⼀般是⽤auto或者模板参数定义的对象去接收 lambda 对象。
lambda表达式的格式:

[捕捉列表]->返回类型 {函数体}
一个简单的lambda表达式:

auto add1 = [](int x, int y)->int {return x + y; };
cout << add1(1, 2) << endl;
//捕捉列表和参数可为空
//返回值可以省略,可以通过返回对象⾃动推导
//如下:
auto add2 = [](int x, int y){return x + y; };
cout << add2(1, 2) << endl;

  1. 捕捉列表:该列表总是出现在 lambda 函数的开始位置,编译器根据[]来判断接下来的代码是否为 lambda 函数,所以捕捉列表可为空当[ ]不能省略。捕捉列表能够捕捉上下⽂中的变量供 lambda 函数使⽤,捕捉列表可以传值和传引⽤捕捉。
  2. 参数列表:与普通函数的参数列表功能类似,如果不需要参数传递,则可以连同()⼀起省略。
  3. 返回值类型:⽤追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。⼀般返回值类型明确情况下,也可省略,由编译器对返回类型进⾏推导。
  4. 函数体:函数体内的实现跟普通函数完全类似,在该函数体内,除了可以使⽤其参数外,还可以使⽤所有捕获到的变量,函数体为空也不能省略{ }。

2.捕捉列表

        lambda 表达式中默认只能⽤ lambda 函数体和参数列表中的变量,如果想⽤外层作⽤域中的变量就需要进⾏捕捉。其中捕捉方式有三种,如下:

  • 显示捕捉:在捕捉列表中显⽰的传值捕捉传引⽤捕捉,捕捉的多个变量⽤逗号分割。[x,y,&z]表⽰x和y值捕捉,z引⽤捕捉。
  • 隐式捕捉:在捕捉列表写⼀个=表⽰隐式值捕捉,即[=],在捕捉列表写⼀个&表⽰隐式引⽤捕捉即,即[&],这样我们 lambda 表达式中⽤了那些变量,编译器就会⾃动捕捉那些变量。
  • 混合捕捉:即有显示捕捉又有隐式捕捉,如[=,&x]表⽰其他变量隐式值捕捉,x引⽤捕捉;[&,x,y]表⽰其他变量引⽤捕捉,x和y值捕捉。当使⽤混合捕捉时,第⼀个元素必须是&或=,并且&混合捕捉时,后⾯的捕捉变量必须是值捕捉,同理=混合捕捉时,后⾯的捕捉变量必须是引⽤捕捉。

        lambda 表达式如果在函数局部域中,他可以捕捉 lambda 位置之前定义的变量,不能捕捉静态局部变量和全局变量,静态局部变量和全局变量也不需要捕捉, lambda 表达式中可以直接使
⽤。这也意味着 lambda 表达式如果定义在全局位置,捕捉列表必须为空。
        默认情况下, lambda 捕捉列表是被const修饰的,也就是说传值捕捉的过来的对象不能修改,mutable加在参数列表(注意不是捕捉列表)的后⾯可以取消其常量性,也就说使⽤该修饰符后,传值捕捉的对象就可以修改了,但是修改还是形参对象,不会影响实参。使⽤该修饰符后,参数列表不可省略(即使参数为空)。

3.原理

        lambda底层确实是仿函数对象,也就说我们写了⼀个lambda 以后,编译器会⽣成⼀个对应的仿函数的类。仿函数的类名是编译按⼀定规则⽣成的,保证不同的 lambda ⽣成的类名不同,lambda参数/返回类型/函数体就是仿函数operator()的参数/返回类型/函数体, lambda 的捕捉列表本质是⽣成的仿函数类的成员变量。

        所以为了方便或增加可读性我们通常都会用lambda来代替仿函数或函数指针。

五、句装器

1.function

        std::function是⼀个类模板,也是⼀个包装器被定义<functional>头⽂件中。 std::function 的实例对象可以包装存储其他的可以调⽤对象,包括函数指针、仿函数、 lambda 、 bind 表达式等,存储的可调⽤对象被称为std::function的⽬标。若std::function不含⽬标,则称它为空。调⽤空std::function的⽬标导致抛出异常。
        函数指针、仿函数、 lambda 等可调⽤对象的类型各不相同, std::function的优势就是统⼀类型,对他们都可以进⾏包装,这样在很多地⽅就⽅便声明可调⽤对象的类型。

语法格式如下:

function<返回类型(参数类型1,参数类型2,......)>    对象名 = 函数指针/仿函数/ lambda / bind 表达式。

示例:

#include<iostream>
#include<functional>
using namespace std;
int add(int x, int y)
{
	return x + y;
}
int main()
{
	function<int(int, int)> fn = [](int x, int y) {return x + y; };
	function<int(int, int)> fm = add;
    //......
	return 0;
}

例如下面这个题可以这么写:

150. 逆波兰表达式求值 - 力扣(LeetCode)

class Solution {
public:
    int evalRPN(vector<string>& tokens)
    {
        stack<int> st;
        unordered_map<string,function<int(int,int)>> mp=
        {
            {"+",[](int x,int y){return x+y;}},
            {"-",[](int x,int y){return x-y;}},
            {"*",[](int x,int y){return x*y;}},
            {"/",[](int x,int y){return x/y;}}
        };
        for(int i=0;i<tokens.size();i++)
        {
            if(mp.count(tokens[i]))
            {
                int a=st.top();st.pop();
                int b=st.top();st.pop();
                st.push(mp[tokens[i]](b,a));
            }
            else st.push(stoi(tokens[i]));
        }
        return st.top();
    }
};

2.bind

bind的使用语法:

auto f=bind(可调用对象,参数1,参数2,......)

        bind是⼀个函数模板,它也是⼀个可调⽤对象的包装器,可以把他看做⼀个函数适配器,对接收的可调用对象进⾏处理后返回⼀个可调⽤对象。 bind可以⽤来调整参数个数和参数顺序
bind 也在<functional>这个头⽂件中。
        调⽤bind的⼀般形式: auto newCallable = bind(callable,arg_list); 其中newCallable本⾝是⼀个可调⽤对象,arg_list是⼀个逗号分隔的参数列表,对应给定的callable的参数。当我们调⽤newCallable时,newCallable会调⽤callable,并传给它arg_list中的参数。
        arg_list中的参数可能包含形如_n的名字,其中n是⼀个整数,这些参数是占位符,表⽰
newCallable的参数,它们占据了传递给newCallable的参数的位置。数值n表⽰⽣成的可调⽤对象
中参数的位置:_1为newCallable的第⼀个参数,_2为第⼆个参数,以此类推。_1/_2/_3....这些占
位符放到placeholders的⼀个命名空间中。如下:

#include<iostream>
#include<functional>
using namespace std;
using placeholders::_1;
using placeholders::_2;
int sub(int x, int y)
{
	return x - y;
}
int main()
{
	//可以调换传参顺序
	auto fn1 = bind(sub, _1, _2);
	auto fn2 = bind(sub, _2, _1);
	cout << fn1(2, 3) << endl;//输出-1
	cout << fn2(2, 3) << endl;//输出1
	//可以固定某些参数
	auto fn3 = bind(sub, 2, _1);
	auto fn4 = bind(sub, _1, 3);
	cout << fn3(1) << endl;
	cout << fn4(5) << endl;
	return 0;
}

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

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

相关文章

生信:TCGA学习(R、RStudio安装与下载、常用语法与常用快捷键)

前置环境 macOS系统&#xff0c;已安装homebrew且会相关命令。 近期在整理草稿区&#xff0c;所以放出该贴。 R语言、RStudio、R包安装 R语言安装 brew install rRStudio安装 官网地址&#xff1a;https://posit.co/download/rstudio-desktop/ R包下载 注意R语言环境自带…

Vue3集成搜索引擎智能提示API

需求&#xff1a; 如何在项目中实现像百度搜索框一样的智能提示效果&#xff0c;如下图所示&#xff1a; 相关知识&#xff1a; 下面是各厂商提供的免费API 厂商请求百度http://suggestion.baidu.com/su?wd中国&cbwindow.baidu.sug必应http://api.bing.com/qsonhs.as…

大数据技术在智慧医疗中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 大数据技术在智慧医疗中的应用 大数据技术在智慧医疗中的应用 大数据技术在智慧医疗中的应用 引言 大数据技术概述 定义与原理 发…

游戏引擎学习第10天

视频参考:https://www.bilibili.com/video/BV1LyU3YpEam/ 介绍intel architecture reference manual 地址:https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html RDTS&#xff08;读取时间戳计数器&#xff09;指令是 x86/x86_64 架构中的…

「QT」文件类 之 QTemporaryDir 临时目录类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定制…

Kettle配置数据源错误“Driver class ‘org.gjt.mm.mysql.Driver‘ could not be found”解决记录

问题描述 错误提示&#xff1a;“Driver class ‘org.gjt.mm.mysql.Driver’ could not be found, make sure the ‘MySQL’ driver (jar file) is installed.” 原因分析&#xff1a; 根据错误提示是缺少了相关的数据源连接jar包。 解决方案&#xff1a; 安装对应的Mysql…

C++《继承》

在之前学习学习C类和对象时我们就初步了解到了C当中有三大特性&#xff0c;分别是封装、继承、多态&#xff0c;通过之前的学习我们已经了解了C的封装特性&#xff0c;那么接下来我们将继续学习另外的两大特性&#xff0c;在此将分为两个章节来分别讲解继承和多态。本篇就先来学…

力扣(LeetCode)283. 移动零(Java)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f439;今日诗词:雾失楼台&#xff0c;月迷津渡&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64f; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主…

运算放大器的学习(一)输入阻抗

输入阻抗 最近需要对运算放大器进行学习&#xff0c;我们后面逐一对其参数进行了解。 首先了解下输入阻抗。 放大电路技术指标测试示意图&#xff1a; 输入电阻&#xff1a; 从放大电路的输入端看进去的等效电阻称为放大电路的输入电阻&#xff0c;如上图&#xff0c;此处考虑…

Python3.11.9下载和安装

一、Python3.11.9下载和安装 1、下载 下载地址&#xff1a;https://www.python.org/downloads/windows/ 选择版本下载&#xff0c;例如&#xff1a;Python 3.11.9 - April 2, 2024 2、安装 双击exe安装 3、配置环境变量 pathD:\Program Files\python3.11.9 pathD:\Progr…

大模型研究报告 | 2024年中国金融大模型产业发展洞察报告|附34页PDF文件下载

随着生成算法、预训练模型、多模态数据分析等AI技术的聚集融合&#xff0c;AIGC技术的实践效用迎来了行业级大爆发。通用大模型技术的成熟推动了新一轮行业生产力变革&#xff0c;在投入提升与政策扶植的双重作用下&#xff0c;以大模型技术为底座、结合专业化金融能力的金融大…

杰控通过 OPCproxy 获取数据发送到服务器

把数据从 杰控 取出来发到服务器 前提你在杰控中已经有变量了&#xff08;wincc 也适用&#xff09; 打开你的opcproxy 软件包 opcvarFile 添加变量 写文件就写到 了 opcproxy.ini中 这个文件里就是会读取到的数据 然后 opcproxy.exe发送到桌面快捷方式再考回来 &#…

Vue3 -- 环境变量的配置【项目集成3】

环境&#xff1a; 在项目开发过程中&#xff0c;至少会经历开发环境、测试环境和生产环境(即正式环境)三个阶段。 开发环境 .env.development测试环境 .env.test生产环境 .env.production 不同阶段请求的状态(如接口地址等)不一样&#xff0c;开发项目的时候要经常配置代理跨…

vxe-table 分享实现无限滚动行方式

Vxe UI vue vxe-table 分享无限滚动行方式 实现无限滚动加载有多种方式&#xff0c;可以使用 scroll 事件&#xff0c;也可以使用 scroll-boundary 事件&#xff0c;能满足不同的需求场景。 以下是分享使用 scroll-boundary 事件的用法。 原理 通过 scrollY.threshold 设置阈…

C++中的栈(Stack)和堆(Heap)

在C中&#xff0c;堆&#xff08;heap&#xff09;和栈&#xff08;stack&#xff09;是两种用于存储数据的内存区域。理解它们的原理和区别&#xff0c;对于优化代码性能和确保代码的安全性至关重要。以下是对C中堆栈的详细解析&#xff0c;包括它们的分配方式、优缺点、应用场…

outlook邮箱关闭垃圾邮件——PowerAutomate自动化任务

微软邮箱反垃圾已经很强大了非常敏感&#xff0c;自家的域名的邮件都能给扔到垃圾邮箱里&#xff0c;但还是在本地增加了一层垃圾邮箱功能&#xff0c;然后垃圾邮箱并没有提示&#xff0c;导致错过很多通知&#xff0c;本身并没有提供关闭的功能&#xff0c;但微软有个Microsof…

FFmpeg的基本结构

FFmpeg框架可以简单分为两层&#xff0c;上层是以ffmpeg、ffplay、ffprobe为代表的命令行工具&#xff1b;其底层支撑是一些基础库&#xff0c;包含AVFormat、AVCodec、AVFilter、AVDevices、AVUtils等模块库。 常用函数如下&#xff1a; 1. AVFormat 封装/解封装模块 avf…

Web性能优化:从基础到高级

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Web性能优化&#xff1a;从基础到高级 Web性能优化&#xff1a;从基础到高级 Web性能优化&#xff1a;从基础到高级 引言 基础优…

MATLAB实战 利用1D-DCGAN生成光谱或信号数据

0.前言 在光谱学或信号处理领域&#xff0c;获取大量高质量的数据可能是一项挑战。利用DCGAN进行“迁移学习”&#xff0c;对抗性地生成光谱或信号数据&#xff0c;具有强化、泛化样本特征的应用潜力。 该实战项目提供了所有源代码与测试数据&#xff0c;旨在帮助学者快速地掌握…

react + ts定义接口类型写法

接口&#xff08;未进行ts定义&#xff09; export async function UserList(params: {// keyword?: string;current?: number;pageSize?: number;},// options?: { [key: string]: any }, ) {return request<API1.UserList>(http://geek.itheima.net/v1_0/mp/artic…