C++11新特性
一 智能指针和智能指针自实现
智能指针是C++11中新特性,c++11 —> c++ 2011
C++14 — C++ 2014 c++17 — C++ 2017
智能指针
在C++库中也是类模板之一
实际上将指针封装在一个类,通过对象来管理指针
作用主要用来管理内存,在c++中,是一种管理资源,避免泄露内存的习惯用法,也称RAII(资源获取及初始化)
在使用系统提供的智能指针
class A
{
public:
A()
{
cout << " A() " << endl;
}
~A()
{
cout << "~A()" << endl;
}
//定义一个测试函数
void func()
{
cout << "A::func()"<<endl;
}
};
//智能指针自实现
template<class T>
class myautoptr
{
public:
explicit myautoptr(T* pa)
{
this->m_pa = pa;
}
~myautoptr()
{
delete m_pa;
}
//重新实现-> 和 *运算重载
//->
#if 1
T* operator ->()
{
return m_pa;
}
#endif
//*
T& operator *()
{
return *m_pa;
}
private:
T* m_pa;
};
int main()
{
#if 0
auto_ptr<A> pa(new A); //构造函数(A*p)
pa->func();
A* aa = new A; //在堆上,创建对象时,那么,程序也很可能忘记释放,那么就造成内存泄露
aa->func();
delete aa;
//auto_ptr 在这个类板中的析构函数怀疑它对某个类型的指针进行了自动释放
/*
A()
A::func()
~A() ----->自动去释放了程序员手动创建的堆对象
*/
#endif
myautoptr<A> paa(new A); //实现自定义智能指针
paa->func();
(*paa).func();
return 0;
}
二 C++ 11 auto 和 decltype关键字
1 auto
auto 关键字定义变量,但这个变量的类型,由编译器自动判断变量的类型
class A
{
public:
A()
{
cout << " A() " << endl;
}
~A()
{
cout << "~A()" << endl;
}
//定义一个测试函数
void func()
{
cout << "A::func()"<<endl;
}
};
int main()
{
auto i = 10; // i 是 int
auto p = new A; // p is A*
//如果类型比较短,使用auto并不见得好,如果类型名字很长,比如类模板
map<int, string> Map;
auto it = Map.begin(); //使用auto可以节省快速 ---map<int, string>::iterator
return 0;
}
二 C++ 11 auto 和 decltype关键字
1 auto
auto 关键字定义变量,但这个变量的类型,由编译器自动判断变量的类型
class A
{
public:
A()
{
cout << " A() " << endl;
}
~A()
{
cout << "~A()" << endl;
}
//定义一个测试函数
void func()
{
cout << "A::func()"<<endl;
}
};
int main()
{
auto i = 10; // i 是 int
auto p = new A; // p is A*
//如果类型比较短,使用auto并不见得好,如果类型名字很长,比如类模板
map<int, string> Map;
auto it = Map.begin(); //使用auto可以节省快速 ---map<int, string>::iterator
return 0;
}
2 decltype
decltype关键字可以用于表达式的类型
有时我们只想从表达式的类型推断出要定义的变量类型,但是不想用其值进行初始化的时候,
C++11新标准引入了decltype类型说明符,它的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。
class A{
public:
double x;
};
//在C++11 中,函数返回的值若为auto,则需要跟decltype
//在C++14 中, 则可以不用decltype
template<class T1,class T2>
auto add(T1 x,T2 y)->decltype (x+y)
{
return x+y;
}
/*
decltype总结:
1. auto 忽略const,decltype保留顶层const
2.对引用操作,auto推出原有类型,decltype推断出为引用
3.对解引用操作,,auto推出原有类型,decltype推断出为引用
4.auto推断会实际执行,,decltype不会执行,只会分析
*/
int main()
{
#if 1
//[1] 跟基本数据类型
int i;
double d;
const int x = 10;
decltype (x) y = 10; //对于decltype保留顶层const
A* a = new A();
decltype (a) x1; // x1 is A*
decltype (a->x) x3; //x3 is double
x3 = 10;
x1->x = 10;
//[2] 跟指针结合
int tempA = 2;
int* ptrTempA = &tempA;
decltype (ptrTempA) decTempA; //常规使用decTempA为一个int*的指针
// declaration of reference variable 'decTempB' requires an initializer
// 表达内容为解引用,decTempB声明表示为一个引用,必须初始化,否则,编译不通过
//decltype (*ptrTempA) decTempB = tempA;
auto decTempc = ptrTempA;
cout << *decTempc << endl;
#endif
//[3] auto 与 decltype的使用 函数的返回值类型auto,则需要decltype来配合使用
auto ret = add(5,5.0);
cout << "ret = " << ret << endl;
return 0;
}
三 Lambda表达式定义
在函数调用的地方,来实现对函数的定义
它的结构为:
一个[]就表示Lambda开始:
- [capture]:捕获列表。捕捉列表总是出现在Lambda函数的开始处。[]是Lambda引出符,
编译器根据该引出符判断,接下来是否是Lambda函数,
捕获列表由0个或者多个捕捉项组成,如果是有多个,中间用逗号隔开,捕捉列表形式:
- [var] 表示值传递,捕捉变量的val的值
2)[=] 表示值传递
3)[&] 或者 [&val] 表示地址传递或者引用传递
4)[=,&a,&b] 表示以引用来捕捉变量 a和b,其他变量使用值传递
5)[&,a,this] 表示以值来捕捉变量 a和this,其他变量使用引用传递
int a = 10,b = 20;
int ret = [=]()->int{return a+b};
2.(parameters):参数列表,可选项,与普通函数的参数列表一致。如果不需要参数传递,可以
连同括号一起省略
3.mutable:mutable修饰符 ---- 可变的,易变的,跟const相对,默认情况下,Lambda
函数总是一个const函数,mutable可以取消常量性,可以在Lambda函数修改参数的值
4.->return-type:返回值 类型,可选项,用追踪返回类型形式声明 函数的返回类型,如果
不需要返回值的时候,那么,也可以把符号"->"一起省略
5.{body/statement}:函数体,内容和写法与普通函数一样
6.specifiers exception attr:异常属性,可选
普通函数组成部分:函数名 参数列表 传参形式 返回值 函数体 const属性 异常属性
Lambda函数组成部分:
(parameters) ------> 参数列表
[=,&] ------> 传参形式
->return-type —> 返回类型
{body/statement} — 函数体
mutable修饰符 —> 取消const属性
基本使用:
//普通函数
int add(int a,int b)
{
return a+b;
}
//假如一个系统中,代码量比较大,
int main()
{
int a =10,b=20;
// cout << add(a,b);
auto ret = [=]()->int{ //默认情况下是一个const 函数
// a++; //不能修改其参数值
return a+b;
};
//为了避免函数的定义和调用的层次清晰,可以使用lambda来在函数调用的地方,来实现功能
auto ret2 = [a,&b]()mutable ->int{
a++; //mutable修饰符允许函数来修改参数值,它将函数的const属性去掉 a = 11,该变量就相当于该lambda函数中局部变量
b = 50; //&以引用的方式传递,可以直接修改外部变量值
return a+b;
};
int retsult = ret2();
cout << retsult << endl; //61
cout << "a = " << a << endl; //10
cout << "b = " << b << endl; //50
return 0;
}
lambda表达式在STL算法库应用
int main()
{
// STL --- for_each算法
/*
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function fn);
InputIterator first ---- 数据的首地址,迭代器头指针,或者 容器的首地址(数组地址)
InputIterator last ----- 容器的末尾地址(最后元素的下一个)迭代器尾指针
*/
int a[5] = {10,2,3,4,5};
int total = 0;
for_each(a,a+5,[&](int& x){
total += x;
x++; //指向数组的下一个元素,将该元素的值获取给x
});
cout << total;
for_each(a,a+5,[=](int a)
{
cout << a << " ";
});
return 0;
}