C++新标准C++11&14-笔记

本文主要内容为 侯捷先生 的《C++新标准C++11&14》课程个人学习记录,并非完全照搬讲义,有机会请读者看原视频。

语法部分 ?


Variadic Templates

数量不定的模板参数,使用 sizeof… 来计算参数个数。

#include<iostream>
#include<string>

void print(void) { std::cout << "end call" << std::endl;}//用于最后一次调用
//任意类型,任意个数
template<typename T,typename... Types>
void print(const T& firstArg, const Types&... args)
{
	std::cout << sizeof...(args)<< " " << firstArg << std::endl;
	
	print(args...);
}

int main()
{
	print(1, 'A', "what", 3.14, std::string("test"));
	return 0;
}
nullptr、auto
Unifrom Initialization在这里插入图片描述#### Initializer_list

这种方式会给变量初始值,同时数据窄化有影响。不一定是报错,一般实现为编译器警告。
在这里插入图片描述
下面为 Initializer_list的实现,其内部包含了一个array对象(只是含有迭代器),由编译器调用其私有构造函数。为了让自定义的类支持统一的初始化操作,可以另外写一份带有 Initializer_list 参数的函数,当两种函数都存在时,优先使用Initializer_list参数的函数。比如:vector、min、max都有其接受 Initializer_list版本。
在这里插入图片描述

explicit

主要用于告诉编译器不要自作聪明,不准偷偷转换类型。此外,视频中给的例子有问题。

=default、=delete

=default :由于当自定义函数后,编译器不再提供默认版本,使用这个方式就可以重新获取(用在所谓大五样,就是那几个编译器默认提供的函数)。
=delete :用于进制编译器默认产生的函数,本质上可以用于任何函数,也可以用在模板特化时,用于过滤一些特定的形参类型。

Alias Template

也成为模板化名。

template<typename T>
using Vec = std::vector<T, MyAlloc<T>>;
Vec<int> coll;
// std::vector<int, MyAlloc<int>> coll;
Template template parameter

在这里插入图片描述
箭头位置代表名为Container的类型是一个以T为模板参数的模板(与Container名字无关,名字只是为了提醒),如果箭头处的class后面再加个T的话,更好理解。当然此时向右侧那样传入参数还会报错,原因是标准库中的 vector有两个参数,平时使用的时候因为有默认参数,只传入一个参数没有影响,但是这里作为 Template template parameter,编译器无法推断,所以要使用前面的模板别名的方式来解决,这样好像新的名称看起来只要一个参数的模板一样。
在这里插入图片描述

Type Alias

类型别名
在这里插入图片描述

using 总结

在这里插入图片描述

noexcept

用于告知编译器该函数保证不丢异常,用于编译器优化,其后面可以写条件,不写默认为true;
在这里插入图片描述
在这里插入图片描述

override

告诉编译器,是为了重写父类虚函数,用于编译器帮助检查。

final

修饰类

class A final
{};
class B :public A //	ERROR 不能将“final”类类型用作基类	
{};

修饰虚函数

class A 
{
public:
	virtual void f() final{};
};
class B :public A
{
public:
	//ERROR 无法重写“final”函数 "A::f" 
	virtual void f() {}
};
decltype

用于获取对象的类型,属于高级版的 typeid。主要用于三个方面。
在这里插入图片描述
在这里插入图片描述
在模板编程中,可用于获取对象的类型信息。
在这里插入图片描述
对于Lambda来说,很难写出他的类型,所以需要使用decltype
在这里插入图片描述

Lambda

其实现可以看作为,编译器生成的相同功能的仿函数来实现。
在这里插入图片描述
在这里插入图片描述
值得注意的是
Lambda没有默认构造函数和赋值函数,如下情况:
在这里插入图片描述

标准库部分 ?


Tuple

在这里插入图片描述
使用继承来实现Tuple
在这里插入图片描述
使用复合来实现Tuple
在这里插入图片描述

右值引用与移动语义

对于临时对象以及使用move后变成的右值,可以认为它本身没有用了,可以将其资源偷走来为另外一个对象赋值。对此增加了使用 **&&**的右值引用,在类中增加使用 **&&**参数的函数来针对这种调用,即为移动语义,以减少不必要的拷贝,增加效率。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完美转发

先看不完美转发,转发过程中由于变成了一个有名对象,就变成了左值,因此转发错误。
在这里插入图片描述
完美转发 :根据本来的类型进行正确调用

#include<iostream>
#include<string>
#include<vector>
using namespace std;

template<typename T>
void print(T& t) {
	cout << "lvalue" << endl;
}
template<typename T>
void print(T&& t) {
	cout << "rvalue" << endl;
}

template<typename T>
void TestForward(T && v) {
	
	print(std::forward<T>(v));
}

int main() {
	TestForward(1);//rvalue
	int x = 1;
	TestForward(x);//lvalue

	return 0;
}

原理可参考我的另外一篇C++ Move与Forward实现原理

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值