目录
Uniform Initialization (一致性初始化)
explicit for ctors taking more than one argument
ranged-based for statement --for循环
variadic-templates可变模版参数
语法:typename…,这三个点已经成为了语言的一部分。
example:
void print()
{
}
template<typename T, typename... Types>
void print(const T& firstArg, const Type&... args)
{
cout<<firstArg<<endl;
print(args...);
}
print(7.5, "hello", bitset<16>(377), 42);
hashtable:根据函数输入参数不同调用1/2/3/4不同方法,具体如下图所示:
tuple
tuple<int, float,string>:允许你放任意东西,这个是你自己指定,变成一个对象。如下图所示:
Space in Template Expressions
模版表达式的空格:模版参数本身也是一个模版,有两个空格。
vector<list<int> > 在每个版本都适用
vector<list<int>> c++11后可以
nullptr and std::nullptr_t
// C++11之后指针可以用 nullptr代替 0 or NULL
void f(int);
void f(void*);
f(0); // call f(int)
f(NULL); // call f(int) if NULL is 0 ambiguous
f(nullptr); // call f(void*)
auto
概念:不用管一个对象的类型,编译器会自己去推理其类型
// #1 c++11 you can declare a var or an object without specifiying type by using auto
auto i = 42;
double f();
auto d = f();
// #2 auto用于2种情况 第一种是type太长 另一种是复杂的表达式 lambda
vector<int> v;
// vector<int>::iterator pos;
// pos = v.begin();
auto pos = v.begin();
auto l = [](int x) -> bool{}//没有名称的函数
example:
list<string> c;
...
list<string>::iterator ite;
ite = find(c.begin(), c.end(), target);
//为了方便,可以用auto
list<string> c;
...
auto ite = find(c.begin(), c.end(), target);//正确写法
auto ite; //错误写法
ite = find(c.begin(), c.end(), target);
//如果每次声明的时候都赋值时,所有的变量都用auto是可以的,但不推荐初学者这样使用。
Uniform Initialization (一致性初始化)
原理: 编译器看到大括号 {t1,t2,tn}变做出一个 Initializer_list 他关联到一个array<T,n> 调用ctor的时候 array内的元素被编译器被逐一赋值给ctor。但如果参数参数是个Initializer_list 那就将参数打包直接发给函数。
// 如何初始化一个对象或变量,c++11 之前 新手很容易困惑 初始化可能发生在() {} =操作符
// c++11 后统一一个方法 用{}
int a[] = {1,2,3,4};
vector<int> v{2,3,4,5,6};
vector<string> city {
"New York", "London", "Beijing"
};
comlex<int> c{4.0, 3.0}; // 等价于 c(4.0, 3.0);
// c++ 11 之前
Rect r1 = {3,7,&area};
Rect r1(3,7,&area);
Initializer Lists
为了完成一致性设初值,大括号背后是做出一个 Initializer_list,个数可变的元素。
1、大括号可以用来设初值。
int i; // i没有定义初值
int j{}; // j定义初值为0
int* p; // 指针p没有初值
int *q{}; // 指针q的初值是nullptr
2、大括号里的元素类型必须一致
从一致性设初值的方式,了解到了{}的作用,下面了解以下 Initializer_list的原理。比如下图例子:
print(定义的容器必须是int类型)。定一个class P类,定义构造函数,测试用例:
#include <iostream>
// #include <initializer_list>
using namespace std;
// 支持函数接受任意个数的参数
// vector<int> v{1,2,3,4,5,6};
// 的实现原理就是将{1,2,3,4,5}包装成initializer_list 调用参数是initializer_list的ctor
void print(initializer_list<int> vals) {
for (auto p = vals.begin(); p!=vals.end(); ++p) {
cout << *p << ' ';
}
cout << endl;
}
class P{
public:
P(int a, int b){
cout << "P(int a,int b)=" <<a << ' ' << b << endl;
};
P(initializer_list<int> initlist) {
cout << "P(initializer_list<int>)=";
for(auto i : initlist) {
cout << i << ' ';
}
cout << endl;
}
};
int main() {
print({1,2,3,4,5,6,7});
P p(77,5);
P q{77,5};
P r{77,5,23};
// 调用构造函数
P s = {77, 5};
}
max/min只能接受两个参数来对比。
array
换个形式的数组。具体的可以看看我写的STL源码剖析:https://blog.csdn.net/qq_27262727/article/details/105248954
explicit for ctors taking more than one argument
概念:explicit用来针对构造函数接受一个以上实参。
explicit(明白的,明确的)接收单一实参example:
下图左边是允许的,下图右边加入explicit之后,不允许要编译器做转换,必须输入跟定义的一致才行,否则会报错。
一个以上输入实参example:
//!表示加入explicit,报错的
ranged-based for statement --for循环
for的新形式:使用:来遍历动作。
//例子1
for(decl : coll) {
statement
}
// 等价于下面
for(auto pos = coll.begin(), end=coll.end(); pos!=end; ++pos) {
decl = *pos
statment
}
//例子2
for(int i : {1,2,3,4,5,1,3}) {
std::cout << i << ' ';
}
for(auto e : v) {
std::cout << e << " ";
}
for(auto& e: v) {
e *= 3;//加入引用,拿出来的东西e会根据操作改变原来元素内容,影响原来的元素,而且引用的话速度会变得很快。
std::cout << e << " ";
}
for循环内部做的事情: