阅读 《深入应用C++11优化代码与工程应用》 学习笔记
// C++ 11 初始化
int i {1};
int i_arr[]{ 1, 2, 3, 4, 5 };
int * pint = new int{ 1 };
int * parr = new int[2]{ 1,2 };
struct A {
int x;
int y;
} A_a = { 1, 2 };
struct B {
int x;
int y;
B(int _x, int _y) :x(_x), y(_y) {}
} B_b = { 1, 2 };
/*
A_a 的初始化过程是C++98/03 中就有的聚合类型(Aggregates)的初始化。 它将以拷贝的形式,用初始化列表中的值来初始化Struct A 成员。
B_b 的初始化时自定义了一个构造函数, 因此, 实际上初始化时以构造函数进行的。
C++ 聚合类型的定义:
1、类型是个普通数组 (如 int[10]、 char[2][3])
2、类型是一个类(class、struct、union)
* 无自定义的构造函数。
* 无私有(private)或保护(protected)的非静态数据成员。
* 无基类。
* 无虚函数。
* 不能有{} 和 = 直接初始化的非静态数据成员。
*/
// 实际上 stl 中的 容器是通过 std::initializer_list 这个轻量级的类模板来完成上述功能支持的
vector varr{ 1, 2, 3, 4, 5 };
// initializer_list 是非常高效的, 它内部并不负责保持初始化列表中元素的拷贝,仅仅存储了列表中元素的引用而已。
vector(_XSTD initializer_list _Ilist,
const _Alloc& _Al = allocator_type())
: _Mybase(_Al)
{ // construct from initializer_list
_Construct(_Ilist.begin(), _Ilist.end());
}
template
class initializer_list
{ // list of pointers to elements
public:
typedef _Elem value_type;
typedef const _Elem& reference;
typedef const _Elem& const_reference;
typedef size_t size_type;
typedef const _Elem* iterator;
typedef const _Elem* const_iterator;
_CONST_FUN initializer_list() _NOEXCEPT
: _First(0), _Last(0)
{ // empty list
}
_CONST_FUN initializer_list(const _Elem *_First_arg,
const _Elem *_Last_arg) _NOEXCEPT
: _First(_First_arg), _Last(_Last_arg)
{ // construct with pointers
}
_CONST_FUN const _Elem *begin() const _NOEXCEPT
{ // get beginning of list
return (_First);
}
_CONST_FUN const _Elem *end() const _NOEXCEPT
{ // get end of list
return (_Last);
}
_CONST_FUN size_t size() const _NOEXCEPT
{ // get length of list
return ((size_t)(_Last - _First));
}
private:
const _Elem *_First;
const _Elem *_Last;
};
// auto 类型推导
auto x = 1; //OK: x 是 int 类型
auto pi = new auto(1); //OK: pi是 int * 类型
const auto u = 1; //OK: u 是 const int 类型
const auto *pv = &x; //OK: pv是 const int * 类型
// auto 使用
map resultMap { { 1, 10 }, { 2, 20 }, };
auto miter = resultMap.begin(); //map::iterator miter = resultMap.begin();
for (; miter != resultMap.end(); ++ miter)
{
cout << miter->second << endl;
}
// C++ 11 decltype
int y = 1;
decltype(y) dv = 2; // dv -> int
// C++ 11 auto 和 decltype 的结合使用
// 返回类型后置语法
// C++ 11 中添加了返回类型后置(trailing-return-type, 又称跟踪返回类型)语法,将decltype 和 auto 结合起来完成返回值类型推导。
template
auto test_add(T t, U u) -> decltype(t + u)
{
return t + u;
}
// 模板使用
// eg: auto res = test_add(1, 1.2);
// C++ 11 模板的改进 (using 别名语法)
// 通过using 定义模板别名的语法, 只是在普通类型别名语法的基础上添加template的参数列表,
// 使用using 可以轻松的创建一个新的模板别名,而不需要像C++98/03那样使用繁琐的外敷模板。
// C++ 98/03
template
struct map_t1
{
typedef std::map mapT;
};
// eg: map_t1::mapT map_1;
// C++ 11
template
using map_t2 = std::map;
// eg: map_t2 map_2;
// 函数模板的默认模板参数
// 当模板有默认参数时,函数模板的调用如同一个普通函数
template
T func(T value)
{
return value;
}
map resultMap { { 1, 10 }, { 2, 20 }, };
// C++ 11 for 循环
for(const auto &v : resultMap)
{
cout << v.second << endl;
}
void func_t(void)
{
//......
}
struct Foo1 {
void operator()(int x) {
cout << x<< endl;
}
};
struct Foo2 {
using foo_t = void(*) (void);
static void func(void) {
//......
}
operator foo_t(void) {
return func;
}
};
struct Foo3 {
int m_a;
void func(void) {
//......
}
};
// 函数指针
void (* p_func)(void) = &func_t;
// 仿函数
vector arr{ 1,2,3 };
std::for_each(arr.begin(), arr.end(), Foo1());
// 可被转换为函数指针的类对象
Foo2 foo_2;
foo_2()
// 成员函数指针
void (Foo3::*p_func)(void) = &Foo3::func;
Foo3 foo3;
(foo3.*p_func)();
std::function fr1 = func_t; // 可以取代函数指针的作用
Foo2 foo2;
fr1 = foo2;
void func_bind(int x, int y) {
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
int main(){
auto fb1 = std::bind(func_bind, std::placeholders::_1, 100);
fb1(101, 200); // out: x= 101 y =100
auto fb2 = std::bind(func_bind, std::placeholders::_2, 200);
fb2(101, 301); // out: x= 301 y =200
auto fb3 = std::bind(func_bind, std::placeholders::_1, std::placeholders::_2);
fb3(100, 200); // out: x= 100 y =200
auto fb4 = std::bind(func_bind, std::placeholders::_2, std::placeholders::_1);
fb4(100, 200); // out: x= 200 y =100
return 0
}
auto lambad_fun1 = [](int i) { return i; };
//lambda 表达式在没有参数列表时,参数列表是可以省略的。
auto lambad_fun2 = [] { return 1; };
class Lambda_Test
{
public:
int i_ = 0;
void func(int x, int y)
{
//auto x1 = [] { return i_; }; // error,没有捕获外部变量
auto x2 = [=] { return i_ + x + y; }; // OK,捕获所有外部变量
auto x3 = [&] { return i_ + x + y; }; // OK,捕获所有外部变量
auto x4 = [this] { return i_; }; // OK,捕获 this 指针
//auto x5 = [this] { return i_ + x + y; }; // error,没有捕获 x、y
auto x6 = [this, x, y] { return i_ + x + y; }; // OK,捕获 this 指针、x、y
auto x7 = [this] { return i_++; }; // OK,捕获 this 指针,并修改成员的值
}
};
int main(){
int a = 0, b = 1;
auto f1 = [] { return a; }; // error,没有捕获外部变量
auto f2 = [&] { return a++; }; // OK,捕获所有外部变量,并对 a 执行自加运算
auto f3 = [=] { return a; }; // OK,捕获所有外部变量,并返回 a
auto f4 = [=] { return a++; }; // error,a 是以复制方式捕获的,无法修改
auto f5 = [a] { return a + b; }; // error,没有捕获变量 b
auto f6 = [a, &b] { return a + (b++); }; // OK,捕获 a 和 b 的引用,并对 b 做自加运算
auto f7 = [=, &b] { return a + (b++); }; // OK,捕获所有外部变量和 b 的引用,并对 b 做自加运算
auto f = [=] { return a; }; // 按值捕获外部变量
a += 1; // a 被修改了
std::cout << f() << std::endl; // 输出?
//lambda 表达式按值捕获了所有外部变量。在捕获的一瞬间,a 的值就已经被复制到 f 中了。之后 a 被修改,但此时 f 中存储的 a 仍然还是捕获时的值,因此,最终输出结果是 0。
//如果希望去修改按值捕获的外部变量应当怎么办呢?这时,需要显式指明 lambda 表达式为 mutable:
//需要注意的一点是,被 mutable 修饰的 lambda 表达式就算没有参数也要写明参数列表。
int a = 0;
auto f2 = [=]() mutable { return a++; }; // OK, mutable
return 0;
}
#include
#include
#include
#include