C++2.0_(11&14)——II

一、template template parameter(模板的模板参数)

template<typename T>
using vec = vector<T, allocator<T>>; //不得在function body内声明
using lst = list<T, allocator<T>>;

template<typename T, template<class> class Container>
class XCLs{
private:
    Container<T> c;
public:
    XCLs(){
        for(long i = 0; i < SIZE; ++i){
            c.insert(c.end(), T());
        }

        output_static_data(T());
        Container<T> c1(c);
        Container<T> c2(std::move(c));
        c1.swap(c2);
    }
};

//use case
XCLs<MyString, vec> c1;

二、noexcept

void foo() noexcept;      //加上noexcept表明,这个函数不会抛出异常
void foo() noexcept(true);//在条件为true时, 表明不会抛出异常
1、对于异常这里不做介绍,但简单说几句。
异常是一定要被处理的。
A调用B,若B抛出异常,且若B不处理,则继续往上面走,到A。(也就是说往源头走直到被处
理)
若一直未被处理,则会调用默认的异常处理函数 std::terminate(); 而这个函数又会调用
std::abort()使得程序中断。
void swap(Type &x, Type &y) noexcept(noexcept(x.swap(y))){
    x.swap(y);
}

2、noexcept的作用是在某种条件下函数不会抛出异常。

class MyString{
private:
    char* _data;
    size_t _len;
public:
    //move constructor
    MyString(MyString&& str) noexcept:_data(str._data), _len(str._len){
        ...
    }

    //move assignment
    MyString& operator=(MyString &&str) noexcept{
        ...
        return *this;
    }
};

三、override(复写、改写)应用于虚函数

1、override的字面意思是复写,改写,应用在虚函数上。

2 override 的作用是:
当我们在子类中重写虚函数时,如果我们不小心把其 参数类型 写错,而在原先,编译器是不会给我们报
错的,在 C++11 出现了 override 关键字;当在虚函数后加上 override 时,编译器会提醒我们。
struct Base{
    virtual void cFunc(float){}
};

struct Derived1:public Base{
    virtual void vFunc(int){} //出错,虚函数的参数类型不对
};

struct Derived2:public Base{
    //出错,虚函数的参数类型不对,但是加入override关键字后,出错会报错
    virtual void vFunc(int) override {}
};

四、final

1、final的作用:

对类修饰:表示此类是最后一个,不会再有下一个类继承此类。
对 虚函数修饰:表示不能再子类中对其重写。

应用场景1:

struct Base1 final{}; //加入final关键字后不可被复写

struct Derived : public Base1{};

应用场景2:

struct Base2{
    virtual void f() final;
};

struct Derived2 : public Base2{
    virtual void f(); //报错,父类的虚函数加了final关键字
};

五、decltype(defines a type equivalent to the type of an expression)

1、C++11引入decltype类型说明符,它的作用是选择并返回操作数的数据类型,在此过程中分析表达式并得到它的类型,却不实际计算表达式的值。

通俗来讲: decltype 的作用其实就是想得到表达式的类型而不是值。
map<string, float> coll;
...
decltype(coll)::value_type elem;

decltype三种应用:

应用1:decltype, used to declare return types(用来声明一个返回类型)

//case 1
template<typename T1, typename T2>
decltype(x+y) add(T1 x, T2 y);

//case 2
template<typename T1, typename T2>
auto add(T1 x, T2 y)->decltype(x+y);

应用2:use it in metaprogramming(元编程)

//按下方使用来看,只可以传入容器类型数据
template<typename T>
void test_decltype(T obj){
    typedef typename decltype(obj)::iterator iType;
}

应用3:used ro pass the type of a lambda

auto cmp = [](const Person& p1, const Person& p2){
    return p1.lastName() < p2.lastName()
}

std::set<Person, decltype(cmp)> coll(cmp);

注意:面对lambde,我们手上往往只有object,没有type。要获得其type就得借助于decltype。

六、Lambdas表达式 

C++11 introduced lambdas, allowing the definition of inline functionality, which can be used as a parameter or a local object. Lambdas change the way the C++ standard library is used.

C++11 引入了 lambda ,它能作为一个内嵌的函数,也能当做一个参数或对象来使用。 Lambda 改变了 C++标准库的使用方式。仿函数或函数对象可以由 Lambda 来代替。例如我们以前在使用排序函数的时 候会用到比较大小,我们 可以写一个函数对象,但现在我们可以用Lambda 来代替。
lambda表达式简单使用:
 
[](){
    std::cout << "hello lambda" << std::endl; 
}

//you can call it directly
[](){
    std::cout << "hello lambda" << std::endl;
}();

//or pass it to objects to get called
auto I = [](){
    std::cout << "hello lambda" << std::endl;
}

I();  //print "Hello lambda"

详细环节介绍:

[...](...) mutable throwSpec -> retType{
    ...
}

1、[]叫做捕获说明符,里面放的是截取外部变量的方式,表示一个lambda表达式的开始。 2、()普通参数列表,是函数传入的参数 
3、mutable表示捕获的变量在函数体内部可否修改。 
4、throwSpec表示抛出异常 
5、->type表示返回类型,如果没有返回类型,则可以省略这部分。这涉及到c++11的另一特性,参见自动类型推导,最后就是函数体部分。 
注意:
mutable throwSpec -> type这三个都是可写可不写,但三个有一个存在,则()必须写,若是三个 一个 都没有,则()可写可不写。 

[]外部变量的捕获规则:

默认情况下,即捕获字段为 [] 时, lambda 表达式是不能访问任何外部变量的,即表达式的函数体内无法访问当前作用域下的变量。
[ captures ] 中的 “captures”” 称为 捕获列表 ,可以捕获表达式外部作用域的变量,在函数体内部直接使 用,这是与普通函数或函数对象最大的不同(C ++ 里的包闭必须显示指定捕获,而LUA 语言里的则是默认直接 捕获所有外部变量。)
捕获列表里可以有多个捕获选项,以逗号分隔,使用了略微新奇的语法,规则如下:
[] :无捕获,函数体内不能访问任何外部变量
[ = ] :以值(拷贝)的方式捕获所有外部变量,函数体内可以访问,但是不能修改。
[ & ] :以引用的方式捕获所有外部变量,函数体内可以访问并修改(需要当心无效的引用);
[ var ] :以值(拷贝)的方式捕获某个外部变量,函数体可以访问但不能修改。
[ & var ] :以引用的方式获取某个外部变量,函数体可以访问并修改
[ this ] :捕获 this 指针,可以访问类的成员变量和函数
[ = & var ] :引用捕获变量 var ,其他外部变量使用值捕获。
[ & var ] :只捕获变量 var ,其他外部变量使用引用捕获。
int id = 0;
auto i = [id]() mutable {
    ...
}

//注:id在lambda表达式中是以值的形式传进去的,不可修改,为了可以在lambda表达式中修改id的值,需要添加mutable关键字
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/weixin_42067873/article/details/107730681
今日推荐