C++11--20分钟了解C++11 (上)

20分钟了解C++ 11

1 初始化列表 Initializer List


//C++ 03中用初始化列表初始化数组
int arr[4] = {3, 2, 4, 5}; vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(4);
v.push_back(5); // C++ 11 做了扩展,可以初始化vector
vector<int> v = {3, 4, 1, 9}; // 调用初始化列表构造函数
// 所以相关的STL容器都更新了,支持初始化列表 // 定义自己的初始化列表构造函数:
#include <initializer_list>
class BoVector {
vector<int> m_vec;
public:
BoVector(const initializer_list<int>& v) {
for (initializer_list<int>::iterator itr = v.begin(); itr!=v.end(); ++ itr)
m_vec.push_back(*itr);
}
}; BoVector v = {0, 2, 3, 4};
BoVector v{0, 2, 3, 4}; // 初始化的另一种方式 // 自动进行常规的初始化
class Rectangle {
public:
Rectangle(int height, int width, int length){ }
}; void draw_rect(Rectangle r); int main() {
draw_rect({5, 6, 9}); // Rectangle{5,6,9}被自动调用
} // 注意:要小心使用
// 1. 可读性非常差,即使有IDE的帮助也是。函数名称很少表示函数所采用的参数类型
// 2. 函数可以被不同参数类型重载,比如下面的情况 void draw_rect(Triangle t);

2 统一初始化Uniform Initialization

// C++ 03
class Dog { // 聚合类或者结构体,直接初始化对应成员
public:
int age;
string name;
};
Dog d1 = {5, "Henry"}; // 可以直接用大括号聚合初始化 // C++ 11 扩展了大括号初始化的范围
class Dog {
public:
Dog(int age, string name) {...};
};
Dog d1 = {5, "Henry"}; //类有合适参数的构造函数 /* 统一初始化的搜索顺序:
* 1. 初始化列表构造函数
* 2. 具有合适参数的常规构造函数
* 3. 聚合初始化(直接初始化对应成员)
*/ Dog d1{3}; class Dog {
public:
int age; // 第3选择 Dog(int a) { // 第2选择
age = a;
} Dog(const initializer_list<int>& vec) { // 第1选择
age = *(vec.begin());
}
};

3 auto类型

std::vector<int> vec = {2, 3, 4, 5};

// C++ 03
for (std::vector<int>::iterator it = vec.begin(); it!=vec.end(); ++ it)
m_vec.push_back(*it); // C++ 11: 使用auto节省大量打字的时间
for (auto it = vec.begin(); it!=vec.end(); ++ it)
m_vec.push_back(*it); auto a = 6; // a is a integer
auto b = 9.6; // b is a double
auto c = a; // c is an integer
auto const x = a; // int const x = a
auto& y = a; // int& y = a // 它是静态类型,没有运行时成本,fat-free.
// 使得代码更易维护 // 1. 当需要类型转换时不要使用auto
// 2. IDE变得很重要

4. foreach

 */
// C++ 03:
for (vector<int>::iterator itr = v.begin(); itr!=v.end(); ++ itr)
cout << (*itr); // C++ 11:
for (auto i: v) { // 任何有begin()和end()的类都能使用
cout << i ; // 只读访问
} for (auto& i: v) {
i++; // 改变v的值,避免拷贝构造
} auto x = begin(v); // 同int x = v.begin(); int arr[4] = {3, 2, 4, 5};
auto y = begin(arr); // y == 3
auto z = end(arr); // z == 5
// 因为数组定义了begin()和end()
// 可以通过给数据的容器定义begin()和end(),使你的代码适配第三方库

5 nullptr

 * 代替C++ 03中的NULL
*/
// NULL具有二义性
void foo(int i) { cout << "foo_int" << endl; }
void foo(char* pc) { cout << "foo_char*" << endl; } int main() {
foo(NULL); // 二义性,调用哪个函数? // C++ 11
foo(nullptr); // 调用foo(char*)
}

6 枚举类 enum class


// C++ 03
enum apple {green_a, red_a};
enum orange {big_o, small_o};
apple a = green_a;
orange o = big_o; if (a == o) //两个不同枚举类型进行比较
cout << "green apple and big orange are the same\n";
else
cout << "green apple and big orange are not the same\n"; // C++ 11
enum class apple {green, red};
enum class orange {big, small};
apple a = apple::green;
orange o = orange::big; if (a == o) //编译失败,因为我们没有定义 ==(apple, orange)
cout << "green apple and big orange are the same\n";
else
cout << "green apple and big orange are not the same\n";

7 static_assert


// 运行时断言
assert( myPointer != NULL ); // C++ 11提供了静态断言,在编译时检查
// 如果int的大小不是4,编译不过
static_assert( sizeof(int) == 4 );

8 委托构造函数


// 一个构造函数想复用另一个构造函数的代码
// 下面这种方法是错误的,会构造两个对象
class Dog {
public:
Dog() { ... }
Dog(int a) { Dog(); doOtherThings(a); }
}; // C++ 03的实现方法:
class Dog {
init() { ... };
public:
Dog() { init(); }
Dog(int a) { init(); doOtherThings(); }
};
/* 缺点:
* 1. 代码笨重.
* 2. 而且init()可能被其他函数调用
*/ // C++ 11 方法:
class Dog {
int age = 9;
public:
Dog() { ... }
Dog(int a) : Dog() { doOtherThings(); }
};
// 限制: Dog()也即被委托的构造函数必须先被调用
上一篇:机器学习——集成学习之Boosting


下一篇:【集成学习】:Stacking原理以及Python代码实现