C++11
参考侯捷C++11&14,《C++ primer》
图中标红部分为自己的笔记理解
1、Spaces in Template Expressions
C++2.0之前的模板在使用时,如果模板参数最后一个符号是> 需要用空格将其与最后的>隔开,否则编译器会把模板参数的最后一个>当成操作符
vector<list<int> >//旧
vector<list<int>>//新
2、nullptr、nullptr_t与NULL
std::nullptr_t 是空指针字面量 nullptr 的类型。它是既非指针类型亦非指向成员指针类型的独立类型。
NULL就是代表0,nullptr就是代表空指针,nullptr_t是nullptr的类型
#define NULL 0//NULL为宏定义
#if defined(__cplusplus) && __cplusplus >= 201103L
#ifndef _GXX_NULLPTR_T
#define _GXX_NULLPTR_T
typedef decltype(nullptr) nullptr_t;
#endif
#include <cstddef>
#include <iostream>
void f(int*)
{
std::cout << "Pointer to integer overload\n";
}
void f(double*)
{
std::cout << "Pointer to double overload\n";
}
void f(std::nullptr_t)
{
std::cout << "null pointer overload\n";
}
int main()
{
int* pi {}; double* pd {};
f(pi);
f(pd);
f(nullptr); // 无 void f(nullptr_t) 可能有歧义
// f(0); // 歧义调用:三个函数全部为候选
// f(NULL); // 若 NULL 是整数空指针常量则为歧义
// (如在大部分实现中的情况)
}
3、语法糖auto
4、initializer_list
5、explicit
显示类型转换运算符,用于构造函数,操作符重载
class A{
public:
explicit A(int y){}
};
A C(3.0);//error
A C(static_cast<int>(3.0));//true
当类型转换为隐式转换时错误,当类型转换为显示转换时正确,也有例外,如果表达式被用作条件,则编译器会将显示的自动类型转换自动用于它(例如运算符重载时)。
6、=default、=delete
构造函数后加=default表示可以重新使用编译器的默认构造函数,
拷贝构造函数加=delete表示不需要任何拷贝构造函数,赋值函数加=delete表示不需要任何赋值含数
析构函数后加=default表示可以重新使用编译器的默认析构函数,析构函数后=delete表示,无法销毁此类型,不能有临时变量,详细《C++ primer》 p450
只能朋友或内部自己拷贝的写法
一般函数不能=default,可以用=delete
Big-Three
7、Alias Template(template typedef)
typedef与using
using
下图为vs2019的vector部分源码
其中部分行有typename,是因为编译器无法知道_Alty_traits的里面有什么类型,告诉编译器_Alty_traits::pointer;是一种类型
8、Template template parameter
很巧妙的解决了上一部分的做法
9、Type Alias
10、noexcept
在函数后加noexcept,表示保证此函数不会抛出异常
11、override
表示父类的虚函数必须重写,不能用于新的函数
12、final
表示继承体系的最后一个不能在被继承,也表示虚函数的最后一个不能在被重写
13、decltype
14、lambdas
15、Variadic Templates
可变参数模板:
例1:
#include "iostream"
#include "bitset"
void printX(){}
template <typename T,typename...Types>
void printX(const T & firstArg,const Types& ...args){
std::cout<<firstArg<<std::endl;
printX(args...);
}
template <typename...Types>
void printX(const Types& ...args){
std::cout<<"*"<<std::endl;
printX(args...);
}
int main(int argc,char *argv[]){
printX(7.8,1,10,"ssss",std::bitset<32>(6555555),55);
return 0;
}
tuple
16、右值引用
示例
iterator
insert(const_iterator __position, const value_type& __x);
iterator
insert(const_iterator __position, value_type&& __x)
{ return _M_insert_rval(__position, std::move(__x)); }
右值可以理解为一个临时对象,右值引用是取得右值的引用(即底层是地址),使用std::move可以将其转移到左值上
打断做法