c++2.0

auto

  • auto不能用来声明函数的返回值。但是如果函数有一个尾随的返回类型,auto是可以声明返回值。
    1
    2
    3
    4
    template<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
    10
    f(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
2
3
4
5
6
7
8
9
10
11
12
13
for ( val declare : collection )
statement
for(int e : arr)
{
e = e*e;
std::cout<<e<<std::endl;
}
template<class InputIterator, class Function>
Function for_each(
InputIterator _First,
InputIterator _Last,
Function _Func
);

override final

  • override:表示函数应当重写基类中的虚函数。(纯虚函数,抽象类)
  • final:表示派生类不应当重写这个虚函数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class 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
    2
    enum class a{one,two,all};
    a ob = a::one;

variadic templates 可变参数列表, 类型和个数任意

1
2
3
4
5
6
7
8
9
10
11
template <class T, class... Args>
void print(const T &first, const Args &... args){
cout<<first<<endl;
print(args...);
}
void print(){}

template< class...T>
void print(const Args &... 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
2
3
4
5
6
shared_ptr<double>pd;
double *p_reg = new double;
pd = p_reg;//错误,不允许隐式转换
pd = shared_ptr<double>(p_reg);//正确
shared_ptr<double> pshared = p_reg;//错误,不允许隐式转换
shared_ptr<double> pshared(p_reg);//正确
  • 不能将smart point 应用非堆内存.
  • 同一个shared_ptr多线程写的情况下,线程不安全。

auto_ptr<T> p(new T);

  • 旧版本的auto_ptr,所有权转移,尽量用新智能指针替代。
  • auto_ptr缺点:
    1. auto_ptr对象不能保存指向静态分配对象的指针。否则,当auto_ptr对象本身被撤销时,它将试图删除指向非动态分配对象的指针,导致未定义的行为。
    2. 不要使用auto_ptr对象保存指向动态分配数组的指针,标准库析构实现采用的是delete。
    3. 所有权无法共享,不支持拷贝赋值。

      weak_ptr<T> p(new T);

  • 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
    10
    template < 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template< class T>
struct __list_node{
void *prev;
void *next;
T data;
};
template< class T,class Ref, class Ptr>
class __list_iterator{
typedef __list_iterator<T,Ref,Ptr> self;
typedef Ptr pointer;
typedef Ref reference;
typedef __list_node<T>* link_type;
link_type node;
bool operator==(const self&x)const{
return node == x.node;
}
reference operator*() const {return (*node).data;}
pointer operator->() const {return &(operator*());}
}

std::bind

  • 将函数、成员函数和闭包转成function函数对象

  • 将多元(n>1)函数转成一元函数或者(n-1)元函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template< 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
    3
    A a();
    auto m = bind(&A::f(),a);
    m();

cast

  1. const_cast
  • ‘const_cast’ 这个操作符可以去掉变量const属性或者volatile属性的转换符,消除对象的常量性.
  1. static_cast
  • ‘static_cast’允许执行任意的隐式转换和相反转换动作,但没有运行时类型检查来保证转换的安全性.
  1. dynamic_cast
  • ‘dynamic_cast’只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程,如果基类没有虚函数,也就无法判断一个基类指针变量所指对象的真实类型, 这时候dynamic_cast只能用来做安全的转换(upercasting),如从派生类指针转换成基类指针,而这种转换其实并不需要dynamic_cast参与。
    . 如果一个引用类型执行了类型转换并且这个转换是不可能的
  1. reinterpret_cast
  • 是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。
  1. 在上行转换中,static_cast和dynamic_cast效果是一样的,而且都比较安全,因为向上转换的对象一般是指向子类对象的子类类型指针;而在下行转换中,由于可以定义就不同了指向子类对象的父类类型指针,同时static_cast只在编译时进行类型检查,而dynamic_cast是运行时类型检查,则需要视情况而定.

未完待续

–…-….-…- -.-..—–.—- -…….——.- -.-.-…..-…- -.——……. -..—……… -..—…-.-.-. -..—.-.—.-. ——–….–.. —-.—……. -.-..–.-.-.-.- ——–….–.. ——.-.-.—- —–..-.—..- –……….-. —-..-.-.—.- -……—-.-.-. -.—.—–…- —.-.-…—– –..-.—-..-.- -.——–.-.– -..—..-.-…. –……….-.

Donate comment here