C++ 11新特性

C++ 11

  1. R-value Reference and Move Constructor
  2. Extern Templates
  3. Constant Expressions
  4. Lambda Function
  5. Delegating Constructor
  6. Uniform Initialization
  7. nullptr

1. R-value Reference - 1

  1. L-values: 具有可通过编程方式访问正在运行的程序的存储地址。
  2. a = 1 + 2
class A{};
int main() {
    A a = A();//r-value
}
  1. 在C++中,非const引用可以绑定到左值,而const引用可以绑定到左值和右值,但是没有什么可以绑定到非const r值。
  2. 右值不可以绑定非常量引用,避免临时变量的修改造成的问题
class A{};
A getA(){
    return A();//右值
}
int main() {
    int a = 1;
    int &ra = a; //OK
    const A &ca = getA();//OK
    A &aa = getA();//ERROR,右值不能给左值引用
}
  1. 右值引用只能绑定在右值上
class A{
    int val;
    void setVal(int v) {
        val = v;
    }
};
A getA(){
    return A();
}
//知道风险,并且想要改变新对象,就是右值引用&&
int main() {
    int a = 1;
    int &ra = a; //OK
    const A &cra = getA();//OK
    A &&aa = getA();//OK
    aa.setVal(2);//OK
    //…
}

1.1. 利用右值构建移动构造函数

class MyArray {
    int size;	
    int *arr;
public:
    MyArray():size(0),arr(NULL){}
    MyArray(int sz):
        size(sz),arr(new int[sz]) {
        //init array here…
    }
    MyArray(const MyArray &other):
        size(other.size), 
        arr(new int[other.size]) {
        for (int i = 0; i < size; i++) {		arr[i] = other.arr[i];
        }
    }
    //main函数中第三种声明方式的移动构造
    MyArray (MyArray &&other):
        size(other.size), arr(other.arr) {
        other.arr = NULL;
    }
    ~ MyArray() {
        delete[] arr;	
    }
}
MyArray change_aw(const MyArray &other)
{
    MyArray aw(other.get_size());
    //Do some change to aw.
    //….
    return aw;
}

int main() {
    MyArray myArr(5);
    MyArray myArr2 = change_aw(myArr);//调用了两次拷贝,先将myArr传入的时候进行一次拷贝,返回之后再次进行拷贝,比较大的开销
    MyArray &&myArr2 = change_aw(myArr);//右值函数,直接用移动构造函数,右值引用造成的维护困难
    MyArray myArr2 = change_aw(myArr);//有了新的移动构造函数,自动适配,15min,提高拷贝速度在C++中使用移动构造函数
}

1.2. Move assignment 拷贝赋值

class MyArray {
public:
    //…
    MyArray &operator=(const
        MyArray &other) {
        if (this == &other)
            return *this;
        if (arr) {			delete[] arr;			arr = NULL;
        }
        size = other.size;
        memcpy(arr, other.arr, size * 	sizeof(int));
        return *this;
    }
    MyArray &operator=(ArrayWrapper
        &&other) {
        size = other.size;
        arr = other.arr;
        other.arr = NULL;
        return *this;	
    }
}
int main() {
    MyArray myArr;
    myArr = MyArr(5);//MyArr是临时对象,19min的内容
}

2. Extern Templates

  1. Avoid of unnecessary instantiation.
//myfunc.h
template<typename T>
    void myfunc(T t){}

//test.cpp
#include "myfunc.h"
int foo(int a){
    myfunc(1);
    return 1;
}
//main.cpp
#include "myfunc.h"
//如果没有以下的模板,那么编译器会先去实例化模板,新的方式外部模板可以避免多次实例化的问题
/*Tell compiler: this instance has been
instantiated in another module!*/
extern template void myfunc<int>(int);

int main() {
    myfunc(1);
}

3. 常量表达式

  1. 提供了更一般的常量表达式
  2. 允许常量表达式使用用户自定义类型
  3. 提供一种方法来确保在编译时完成初始化
  4. 必须在编译的时候可以确定常量表达式

3.1. Ex1

enum Flags { GOOD=0, FAIL=1, BAD=2, EOF=3 };
constexpr int operator| (Flags f1, Flags f2)  {
    return Flags(int(f1)|int(f2));
}//如果不加constexpr则结果被认为是变量不能使用在case中
void f(Flags x) {
    switch (x) {
        case BAD: /* ... */break;
        case EOF: /* ... */ break;
        case BAD|EOF: /* ... */ break;//OK,必须是简单的确认的值
        default: /* ... */ break;
    }
}
void f(Flags x) {
    switch (x) {
        case bad_c(): /* ... */break;
        case eof_c(): /* ... */ break;
        case be_c(): /* ... */ break;
        default: /* ... */ break;
    }
}
constexpr int bad_c();
constexpr int eof_c();
constexpr int be_c();

3.2. Ex2 常量对象

  1. 所有评估都可以在编译时完成。 因此,提高了运行时间效率。
  2. 编译时确定的
struct Point {
    int x,y;
    constexpr Point(int xx, int yy) : x(xx), y(yy) { }
};
int main() {
    constexpr Point origo(0,0);//完全常量,在常量表上
    constexpr int z = origo.x;

    constexpr Point a[] = {Point(0,0), Point(1,1), Point(2,2) };
    constexpr int x = a[1].x; // x becomes 1
}

4. Lambda Function

  1. Also names as Lambda Expression.
  2. A mechanism for specifying a function object

4.1. Ex1

bool cmpInt(int a, int b) {return a < b;}
class CmpInt {
    bool operator()(const int a, const int b) const {
        return a < b;
    }
};
int main() {
    std::vector<int> items { 4, 3, 1, 2 };
    std::sort(items.begin(), items.end(), cmpInt); //Function Pointer
    std::sort(items.begin(), items.end(), CmpInt()); //Function Object (Functor)
    std::sort(items.begin(), items.end(), 
        [](int a, int b) { return a < b; } //Lambda Function
    );
    return 0;
}
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp) {
    //…
    if ( comp(*it1, *it2) )
    //…
}
//std::function 是C++对所有可调用的函数的封装
std::function<bool(int, int)> f1(cmpInt);
std::function<bool(int, int)> f2(CmpInt);
std::function<bool(int, int)> f3([](int a, int b) { return a < b;} );

4.2. Ex2

vector<string> str_filter(vector<string> &vec, function<bool(string &)> matched){
    vector<string> result;
    for (string tmp : vec) {
        if (matched(tmp))
            result.push_back(tmp);
    }
    return result;
}
//可以会用局部变量,40min
int main(){
    vector<string> vec = {"www.baidu.com", "www.kernel.org", "www.google.com"};
    string pattern = ".com";
    vector<string> filterd = str_filter(vec,
        [&](string &str) {
            if (str.find(pattern) != string::npos) 
                return true;
            return false;
        });
}

4.3. Lambda capture

符号含义
[]Capture nothing
[&]Capture any referenced variable by reference
[=]Capture any referenced variable by making a copy
[=, &foo]Capture any referenced variable by making a copy, but capture variable foo by reference
[bar]Capture bar by making a copy; don’t copy anything else

5. Delegating Constructor

#define MAX 256
class X {
    int a;
    void validate(int x) { if (0<x && x<=MAX) a=x; else throw bad_X(x); }
public:
    X(int x) { validate(x); }
    X() { validate(42); }
    // ...
};
class X {
    int a;
public:
    X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); }
    X() :X(42) { }
    // ...
};
X(int x = 42) ?

6. Uniform Initialization

//Old style initialization
vector<int> vec;
vec.push_back(1);
//…
//New style initialization
vector<int> vec = {1, 2, 3};
//Compiler will translate {} as initializer_list<int> 新的初始化表
template class vector<T> {
    //..
    vector(initializer_list<T> list) {
        for (auto it = list.begin(); it != list.end(); ++it)
            push_back(*it);
    }
};
int arr[] = {1, 2, 3}; //OK
vector<int> vec = {1, 2, 3};  
A a= {1, 2, 3}; 

class A{
    int x, y, z;
    //Default generated by compiler
    A(initializer_list<int> list) {
        auto it = list.begin();
        x = *it++;
        y = *it++;
        z = *it;
    }
};
//Uniform Initialization achieved!
int arr[] = {1, 2, 3};
vector<int> vec = {1, 2, 3};
A  a = {1, 2, 3};

7. nullptr

void f(int);//f(0)
void f(char*);

f(0);         	// call f(int)
f(nullptr);   	// call f(char*)

f(NULL);// call f(int)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值