总结自《C++标准库》(第2版)
Template表达式内的空格可以去掉
旧式写法:vector<list<int> >;
新式写法:vector<list<int>>;
nullptr新关键字表示空指针
允许使用nullptr取代0或者NULL,代表一个pointer,并且不会转换成任何整数类型。避免用NULL给指针后传参时导致的anbiguous。
void f(int);
void f(void*);
f(0); //调用f(int);
f(NULL); //调用f(int);
f(nullptr); //调用f(void*);
auto完成类型自动推导
auto声明的变量会根据其初始化值的类型推导出变量的类型。一定要一个初始化操作
auto i=42; //i的类型为int
auto在类型或表达式很复杂时很有用,如lambda表达式中或者各种迭代器中。
花括号进行一致性初始化
任何初始化动作都可以使用花括号进行初始化赋值,但是初始过程中不允许出现窄化(降低精度或造成数值变动)现象。
vector<int> v{2,3,4,5,6}; //OK
int a{3}; //OK
int b{3.0}; //ERROR:窄化,由double变成int
initializer_list进行传参
可以使用class template std::initializer_list<>用来支持以一系列值进行初始化,在传参过程中,使用花括号包裹传递。
void print(std::initializer_list<int> vals)
{
for (auto p = vals.begin(); p != vals.end(); ++p)
cout << *p << endl;
}
print({ 1, 2, 3, 4, 5 }); //调用
for循环新用法
decl是coll集合中的每个元素的声明,当元素在for循环中被初始化为decl,不得有任何显示类型转换。
for(decl:coll)
{
statement;
}
//示例
vector<int> vals{ 1, 2, 3, 4, 5 };
for (auto v : vals)
{
cout << v << endl;
}
move和Rvalue Reference右值引用
move操作主要是減少不必要的拷贝和临时对象。
在传递参数过程中可能会出现很多拷贝赋值的过程,但是临时对象本就在后续过程中不会再被使用,大量的拷贝(分配空间再赋值)会浪费很多时间和资源,所以将其改为右值引用的方式,即将自己这片空间的指针指向临时对象所指向的地址,并将临时对象的那个指针设置为不可再用来实现。
std::move()自身不做任何moving工作,只是将实参转成一个rvalue reference。
rvalue(不具名的临时对象只能出现在赋值操作的右侧) reference可以改变此临时对象的内容。
Raw String Literal
使用R"delim(...)delim"
的形式写字符序列,可以不用像之前那样想写“\”但是要加转义字符导致写成“\”。
//以下a和b相等,均输出a\b
string a = "a\\b";
string b = R"del(a\b)del";
noexcept
用来指明某个函数无法或不打算抛出异常。“绝不抛出”异常不需要额外开销。
void foo() noexcept(...)
其中noexcept(...)
中为true则不抛出异常。
constexpr
可以让表达式和定于编译期。
Variadic Template
template可以接受个数不定的template实参,即三个点,注意递归的结束条件,即第一个void print()
函数
void print()
{
}
template<typename T,typename... Types>
void print(const T& firstArg,const Types&... args)
{
cout << firstArg << endl;
print(args...);
}
int main()
{
print(1, 3, "hello world");
return 0;
}
Alias Template
带别名的模板,和typename比较
template<typename T>
using Vec=std::vector<T,MyAlloc<T>>;
...
Vec<int> coll; //等价于std::vector<int,MyAlloc<int>> coll;
Lambda
语法:
[...](...){
...
};
如
auto foo=[](int args)
{
cout << args << endl;
};
foo(1); //输出1
其中方括号表示引入,其内可以指明一个所谓的capture,用来在lambda内部访问“nonstatic对象”。小括号内可以指明参数。如果有返回类型,则在小括号右边加上-> 返回类型
即可,如下:
auto foo=[](int args)->int
{
return args * 2;
};
cout << foo(1) << endl;
lambda表达式可以定义于语句或表达式内部,可以当做inline函数使用,上面的auto foo=
相当于给lambda表达式一个名字,叫做foo,然后可以当做正常函数那样调用。
decltype
可以让编译器找出表达式类型
std::map<std::string,float> coll;
decltype<coll>::value_type elem;