C++11(新的类功能,可变参数模板,empalce函数)

2023-10-11 07:44

本文主要是介绍C++11(新的类功能,可变参数模板,empalce函数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、类的新功能

1、默认成员函数

2、类成员变量初始化

3、关键字default

4、关键字delete

5、final与override关键字

二、可变参数模板

1、递归函数方式展开参数包

2、逗号表达式展开参数包

 三、empalce_back函数


一、类的新功能

1、默认成员函数

原来C++类中,有6个默认成员函数:
1、 构造函数
2、 析构函数
3、 拷贝构造函数
4、拷贝赋值重载
5、取地址重载
6、const 取地址重载

默认成员函数就是我们不写编译器会生成一个默认的。

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

 而在下面的情况中,我们需要自己写移动构造和移动赋值:

1、拷贝对象需要深拷贝时,自己写移动构造和移动赋值,比如:string,vector,list。

2、针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:

* 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造。


* 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似)


* 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。

注:一般来说,要写析构函数的类那么就需要自己写移动构造和拷贝构造。 

2、类成员变量初始化

C++11支持非静态成员变量在声明时进行初始化赋值,但是要注意这里不是初始化,这里是给声明的成员变量缺省值。

class B
{
public:B(int b = 0):_b(b){}int _b;
};
class A
{
public:void Print(){cout << a << endl;cout << b._b << endl;}
private:// 非静态成员变量,可以在成员声明时给缺省值。int a = 10;B b = 20;
};

3、关键字default

强制生成默认函数的关键字。

C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用default关键字显示指定移动构造生成。

class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}//拷贝构造函数Person(const Person& p):_name(p._name),_age(p._age){}Person(Person&& p) = default;
private:string _name;int _age;
};

4、关键字delete

禁止生成默认函数的关键字。

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

5、final与override关键字

final : 修饰一个类,使它不能够被继承。final既可以修饰类也可以修饰虚函数。修饰虚函数,表示该虚函数不能再被重写。

override : 在继承中,检查子类是否重写了父类的虚函数,没有重写就报错。


二、可变参数模板

C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,而在C++98/03中,类模版和函数模版中只能含固定数量的模版参数。

下面就是一个基本可变参数的函数模板:

Args是一个模板参数包,args是一个函数形参参数包
声明一个参数包 Args...args,这个参数包中可以包含0到任意个模板参数。

template <class ...Args>
void ShowList(Args... args)
{}

我们在使用时可以传入不同个数的参数,如下:

int main()
{string s("hello");ShowList();ShowList(1);ShowList(1, 'A');ShowList(1, 'A', s);return 0;
}

语法不支持使用args[i]这样方式获取可变参数,那么我们要如何一一取出参数包里的参数呢? 取出方法如下:只能通过展开参数包的方式来获取参数包中的每个参数。

1、递归函数方式展开参数包

// 递归终止函数
​void ShowList()
{cout << endl;
}// 展开函数
template<class T, class ...Args>
void ShowList(const T& val, Args... args)
{cout<<val<<" ";ShowList(args...);
}

2、逗号表达式展开参数包

这种展开参数包的方式,不需要通过递归终止函数。这种就地展开参数包的方式实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。

template <class T>
void PrintArg(const T& t)
{cout << t << " ";
}//展开函数
template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args), 0)... };cout << endl;
}

 三、empalce_back函数

我们看vector中的empalce_back 就使用了上面所讲到的参数包。我们来看个关于push_back 和 emplace_back用法的例子:

vector<pair<string, int>> v;v.push_back(make_pair("sort", 1));v.emplace_back(make_pair("sort", 1));
v.emplace_back("sort", 1));

push_back 和 emplace_back都可以插入数据,但是后者的第二种插入方式是不是更简便一些呢?两者又有什么区别呢?

首先,push_back 的插入需要先构造一个 pair 的变量,然后再拷贝构造。emplace_back 的插入则是既可以像 push_back那样用,也可以用参数包的形式,依次取出参数,第一次取出的参数去初始化 pair的first,第二次取出的参数去初始化 pair 的 second。所以在这种情况下 emplace_back 的效率比push_back的高。只有模板的可变参数包能够实现 emplace_back 的这种用法。

这篇关于C++11(新的类功能,可变参数模板,empalce函数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/186575

相关文章

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

SpringBoot集成EasyPoi实现Excel模板导出成PDF文件

《SpringBoot集成EasyPoi实现Excel模板导出成PDF文件》在日常工作中,我们经常需要将数据导出成Excel表格或PDF文件,本文将介绍如何在SpringBoot项目中集成EasyPo... 目录前言摘要简介源代码解析应用场景案例优缺点分析类代码方法介绍测试用例小结前言在日常工作中,我们经

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数