auto
- auto不能用来声明函数的返回值。但是如果函数有一个尾随的返回类型,auto是可以声明返回值。
1
2
3
4template<class T1, class T2>
auto test(T1 t1,T2 t2) -> **decltype**(t1 + t2){
return t1+t2;
}
std::array
- array对象的长度是固定的,使用了静态存储区,即存储在栈上,效率跟数组相同,但是更加的安全。
nullptr
- nullptr->void*
- nullptr是std::nullptr_t。存在和任何指针类型以及类成员指针类型的空值,bool类型的隐式转换。
- 不存在整型的隐式转换。
1
2
3
4
5
6
7
8
9
10f(int *p){}
f1(bool o){}
f2(std::share_ptr<int> p){}
int p1 = NULL;
int p2 = nullptr;
if(p1==p2);
f(p2);
f1(p2);
f2(p2);
int i = nullptr; //false
基于范围的for循环
1 | for ( val declare : collection ) |
override final
- override:表示函数应当重写基类中的虚函数。(纯虚函数,抽象类)
- final:表示派生类不应当重写这个虚函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class A{
public:
virtual void func(int i){
cout<<"A::f"<<endl;
}
};
class B : public A{
public:
virtual void func(long l) final {
cout<<"B::f"<<endl;
}
};
class C : public A{
public:
virtual void func(int i) override {
cout<<"B::f"<<endl;
}
};
强类型枚举
- 传统enum会将常量暴露在外层作用域。存在隐式整型转型。
- 强类型枚举由关键字enum class标识,不存在隐式转整型。
1
2enum class a{one,two,all};
a ob = a::one;
variadic templates 可变参数列表, 类型和个数任意
1 | template <class T, class... Args> |
智能指针 pointer-like classess
#include<memoray>
- 智能指针构造函数是explicit,拒绝内置指针隐式转换为智能指针。
- shared_ptr<T> 可以指向同一地址空间,通过count计数,防止成为空悬指针。
- unique_ptr<T> 独占内存空间。
- 不要使用get()初始化指针,会产生未定义行为。
常用共有函数列表
- p.get() 返回内置指针。
- swap(a,b) a.swap() 交换指针
shared_ptr<T> p 独有函数
- make_shared<T>(arg) 返回一个指针 指向用arg初始化的对象。
- shared_ptr<T> p(q) 拷贝构造函数赋值。
- p.unique()->bool
- p.use_count()->int
1 | shared_ptr<double>pd; |
- 不能将smart point 应用非堆内存.
- 同一个shared_ptr多线程写的情况下,线程不安全。
auto_ptr<T> p(new T);
- 旧版本的auto_ptr,所有权转移,尽量用新智能指针替代。
- auto_ptr缺点:
- weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的 shared_ptr. weak_ptr只是提供了对管理对象的一个访问手段. 弱引用并不修改该对象的引用计数, 这意味这弱引用它并不对对象的内存进行管理.
- weak_ptr指向shared_ptr指针指向的对象的内存,却并不拥有该内存。
- 解决shared_ptr环形引用的问题.(两个对象各自包含指向彼此的shared_ptr成员,形成环状引用,引用计数永远为1,不能销毁,造成内存泄漏).
unique_ptr<T> p(new T);
- unique_ptr<T> 拒绝拷贝和赋值。但可以通过u.reset() .u.release()间接拷贝和赋值。
- release()->pointer u.reset(m) 提供可选指针参数列表,u = m
1
2
3
4
5
6
7
8
9
10template < class T>
class shared_ptr{
private:
T *p;
public:
shared_ptr(T *pm):p(pm){}
T& operator*() const{return *p;}
T* operator->() const{return p;}
};
//->运算符作用之后得到的输出继续用->作用。
迭代器 pointer-like classes
1 | template< class T> |
std::bind
将函数、成员函数和闭包转成function函数对象
将多元(n>1)函数转成一元函数或者(n-1)元函数
1
2
3
4
5
6
7
8
9
10
11
12template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
template< class R, class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
auto x1 = bind(f,10,20,10);
auto x2 = bind(f,std::placeholders::_1,2,3);
auto x3 = bind(f,std::placeholders::_1,23,std::placeholders::_2);
auto x4 = bind<double>(f,std::placeholders::_1,std::placeholders::_2,5);
cout<<x1()<<endl;
cout<<x2(1)<<endl;
cout<<x3(20,32)<<endl;
cout<<x4(23,12)<<endl;某些无法拷贝的参数,只能使用引用传递,需要使用ref
1
for_each(words.begin(),words.end,bind(print,ref(os),_1,' '));
bind 无法绑定重载函数,因为重载函数参数个数不同。
bind 绑定成员函数,需要类的实例作为第二个参数。
bind 绑定成员函数,不需要类实例。
1
2
3A a();
auto m = bind(&A::f(),a);
m();
cast
- const_cast
- ‘const_cast’ 这个操作符可以去掉变量const属性或者volatile属性的转换符,消除对象的常量性.
- static_cast
- ‘static_cast’允许执行任意的隐式转换和相反转换动作,但没有运行时类型检查来保证转换的安全性.
- dynamic_cast
- ‘dynamic_cast’只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程,如果基类没有虚函数,也就无法判断一个基类指针变量所指对象的真实类型, 这时候dynamic_cast只能用来做安全的转换(upercasting),如从派生类指针转换成基类指针,而这种转换其实并不需要dynamic_cast参与。
. 如果一个引用类型执行了类型转换并且这个转换是不可能的
- reinterpret_cast
- 是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。
- 在上行转换中,static_cast和dynamic_cast效果是一样的,而且都比较安全,因为向上转换的对象一般是指向子类对象的子类类型指针;而在下行转换中,由于可以定义就不同了指向子类对象的父类类型指针,同时static_cast只在编译时进行类型检查,而dynamic_cast是运行时类型检查,则需要视情况而定.
未完待续
–…-….-…- -.-..—–.—- -…….——.- -.-.-…..-…- -.——……. -..—……… -..—…-.-.-. -..—.-.—.-. ——–….–.. —-.—……. -.-..–.-.-.-.- ——–….–.. ——.-.-.—- —–..-.—..- –……….-. —-..-.-.—.- -……—-.-.-. -.—.—–…- —.-.-…—– –..-.—-..-.- -.——–.-.– -..—..-.-…. –……….-.