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

相关文章

苹果macOS 26 Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色

《苹果macOS26Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色》在整体系统设计方面,macOS26采用了全新的玻璃质感视觉风格,应用于Dock栏、应用图标以及桌面小部件等多个界面... 科技媒体 MACRumors 昨日(6 月 13 日)发布博文,报道称在 macOS 26 Tahoe 中

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

Java反射实现多属性去重与分组功能

《Java反射实现多属性去重与分组功能》在Java开发中,​​List是一种非常常用的数据结构,通常我们会遇到这样的问题:如何处理​​List​​​中的相同字段?无论是去重还是分组,合理的操作可以提高... 目录一、开发环境与基础组件准备1.环境配置:2. 代码结构说明:二、基础反射工具:BeanUtils

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示