Outlines
新基础类型
- 虽然随着C99加入了
long long
类型而且编译器很早便支持了这个类型,但是直到C++11才正式加入标准 UTF-8
是一种可变长度的编码方法,一般直接用char
类型处理(C++20加入了char8_t
以和普通字符区分). 而UTF-16
和UTF-32
编码则分别对应char16_t
和char32_t
.
命名空间
- 可以内联命名空间,
inline namespace V2
,利用此特性可以无缝升级库代码 - C++17 可以嵌套命名,
namespace A::B::C{ ... }
auto
- 推导时会忽略cv限定符(即忽略原来的
const
,volatile
),但也可以重新添加 - C++14支持返回类型
auto
自动推导
template<class T1, class T2>
auto sum(T1 a1, T2 a2){
return a1 + a2;
}
decltype
- 五条推导规则:
decltype(e)
,其中e
的类型为T
- 如果没加括号,则推导为T(父对象的cv限定符不会同步到成员变量的推导)
- 如果为函数或仿函数,则为其返回值类型
- 如果是左值,则推导为
T&
- 如果是将亡值,则推导为
T&&
- 除此之外推导为
T
函数返回类型后置
比如返回函数指针类型,使用函数返回类型后置更好(传统需要typedef
一个函数指针类型)
auto foo2()->int(*)(int)
{
return bar_impl; // int bar_impl(int x);
}
右值引用
- 左值(lvalue)一般指一个指向特定内存的具有名称的值(具名对象),有相对稳定的内存地址(可以通过取址符取到地址),而且有一段较长的生命周期;而纯右值(prvalue)则是不具名对象(不能取到地址,比如
&1
是错误的),生命周期短,通常是暂时性的.将亡值(xvalue)是泛左值(包含左值)和右值(包含纯右值)的交集,出现的途径有:1.泛左值类型转换为右值引用 2.临时量实质化 - 使用左值引用以避免危险的指针,
int &x=y;
- 右值引用,
int &&k=11;
- 复制构造函数是左值引用,执行深拷贝,要复制源对象;而移动构造函数则是右值引用,直接将源对象进行修改替换.但函数形参即便是一个右值引用本质也是一个左值,可以使用
std::move()
来强制左值转右值.
void move_pool(memPool &&pool){
memPool new_pool(std::move(pool));
// memPool new_pool(static_cast<memPool&&>(pool));
}
STL的很多容器都支持了移动构造和移动赋值
std::string str1 = "apple";
vec.push_back(std::move(str1)); // 避免了深拷贝,但同时str1也不再存在了
- 得益于C++11添加的引用折叠规则,我们能够实现: 万能引用
auto &&
即既可以绑定左值也可以绑定右值,如果给左值,则推导为左值引用,如果给右值则推导为右值引用;完美转发就利用万能引用,实现无多余临时复制的转发,可使用std::forward<T>()
函数模板进行完美转发
template<class T>
void perfect_forwarding(T &&t){
some_func(std::forward<T>(t));
// some_func(static_cast<T&&>(t));
}
lambda表达式
- 只能捕获非静态的局部变量(即自动存储类型),而全局变量和局部变量不必捕获直接用就行了
int x=1;
int main(){
int y=2;
static int z=3;
auto foo = [y] {return x + y + z; };
}
- 捕获变量默认为常量,捕获引用和
mutable
说明符才可以修改变量,但是mutable
捕获的值不会改变外部值,而捕获引用会同步修改,而且mutable
捕获值的修改会影响下一次调用时的值(类似static
)
auto foo = [x, &y] () mutable { ... };
[=]
捕获全部变量值,[&]
捕获全部变量的引用,[this]
捕获this
指针; C++20中,用[=, this]
代替[=]
,以强调和[=, *this]
的差别,后者是捕获this
对象的副本.- C++14支持了广义捕获
std::string x = "hello ";
auto foo = [x = std::move(x)] { return x + "world"; };
默认和删除函数
- 可以显式添加或删除特殊成员函数
class NonCopyable{
public:
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
// ...
}
委托构造函数
可以复用构造函数
class X{
public:
X(): X(0, 0.) {}
X(int a): X(a, 0.) {}
X(double b): X(0, b) {}
X(int a, double b): a_(a), b_(b) { CommonInit(); }
private:
void CommonInit(){}
int a_;
double b_;
};
继承构造函数
可以直接将基类的构造函数引入
class Derived : public Base {
public:
using Base::Base;
}
强枚举类型
解决传统枚举类型的类型安全问题
enum class HighSchool : unsigned int{
student, teacher, principal
};
HighSchool x = HighSchool::student;
override和final说明符
override
覆盖基类的虚函数overload
即重载,函数名相同但形参不同overwrite
final
该虚函数不能被派生类重写
基于范围的for循环
std::for_each(index_map.begin(), index_map.end(), print);
for(const auto &e : index_map) {...}
支持初始化语句的if/switch
if(bool b=foo(); b){
// ...
}else if(bool b2=bar(); b2){
// ...
}
静态断言
static_assert(sizeof(int) < 4);
结构化绑定
auto return_tuple(){
return std::make_tuple(11, 7);
}
auto [x, y] = return_tuple(); // x=11, y=7
struct BindTest{
int a=42;
std::string b="hello";
}
BindTest bt;
auto[x, y] = bt; // x=42, y="hello"
本文采用知识共享署名4.0国际许可协议(CC BY 4.0)进行许可