c++11中的一些新写法

现在一些开源库里,越来越多c++17的写法了,不过c++17的支持度还不是非常广泛,但c++11已经相当普遍了。没有系统地分析c++11的新特性,在此把一些有用的写法整理整理。

用using来代替typedef

typedef用起来也不错,但是理解起来确实没有using清晰:

using ItemType = pair<int, string>;
using ItemListType = vector<ItemType>;
using FuncPtr = void (*)(int);

初始化列表

花括号初始化列表给写代码带了很大的简洁性,而不用一个一个insert()了,结构体也不用一个一个字段赋值了:

struct Student
{
    int age;
    string name;
    float height;
};

int main()
{
    Student s1 = {24, "zhangsan", 1.78f};
    auto s2 = Student{24, "zhangsan", 1.78f};

    int *arr = new int[10]{1,2,3};
}

简单一致的遍历

如果对于一个普通数组,我们以往遍历时这么写:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) {
    ...
}

但其实这么写也是支持的:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
for (auto it = begin(arr); it != end(arr); ++it) {
    cout << *it << endl;
}
for (auto one : arr) {
    cout << one << endl;
}

当然更推荐使用array来创建一个数组:

array<int, 10> arr = {1,2,3,4,5,6,7,8,9,10};

好用的lambda

lambda配合起一些算法参数,变得非常方便,也不用传函数指针,也不用传仿函数(functor) 了。

array<int, 10> arr = {1,2,3,4,5,6,7,8,9,10};
for_each(arr.begin(), arr.end(), [](int n) { cout << n << endl; });
for_each(user_rank.begin(), user_rank.end(), [](pair<const int, string>&one) { cout << one.first << ":" << one.second << endl;});

再比如排序:

sort(arr.begin(), arr.end(), [](int x, int y) -> bool { return x >= y; });

lambda的写法格式如下:

[capture list] (params list) mutable exception-> return type { function body }

其中的捕获方式罗列如下:

捕获形式 说明
[] 不捕获任何外部变量
[变量名, …] 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符)
[this] 以值的形式捕获this指针
[=] 以值的形式捕获所有外部变量
[&] 以引用形式捕获所有外部变量
[=, &x] 变量x以引用形式捕获,其余变量以传值形式捕获
[&, x] 变量x以值的形式捕获,其余变量以引用形式捕获

提高性能的move

关于move(),关于右值有很多可以说的,也不是很好理解。不过至少知道,move是直接交出数据所有权以减少数据拷贝,达到提升性能的目的。最最常用的例子就是,传递一个非常大的字符串string:

string description = "...";
student.description = move(description);

其实内部就是拷贝了一下string::data()指针而已。

交换两个字符串,使用move也非常合适,但直接使用std::swap()更好。千万不能当整型一样,写成auto t = s1; s1 = s2; s2 = t;

remove_if使用

通常我们删除vector中的数组时,我们得这么写:

vector<int> arr = {1,2,3,4,5,6,7,8,9,10};
for (auto it = arr.begin(); it != arr.end();) {
    if (*it < 5) {
        it = arr.erase(it);
    } else {
        ++it;
    }
}

使用remove_if可以写成:

arr.erase(remove_if(arr.begin(), arr.end(), [](int n) -> bool { return n < 5; }), arr.end());

注意:remove_if并不会删除数据,只是将符合条件的移到末尾,所以还需要借助erase()来真正的删除。如果只是针对指定的某个值,可以使用常规版本remove()。remove_if不支持map/set之类的关联容器,所以对于关联容器还是得按照上面的写法进行。

override和final使用

在以前子类重载基类的方法时,我们都知道声明要一致。这时候因为语法要求的不严格,会导致一些问题,即子类的方法前的 virtual 可以不写,这时光看子类代码是不知道该方法是否为重载方法,而且一旦基类的方法有修改,会发现编译无问题,导致很容易忘记修改子类中重载的方法。

override就指明该方法一定是重载基类中的某函数的,final表示修饰的方法不允许子类继续重载。

class A
{
public:
    virtual int add(int a, int b) {
        return a + b;
    }
};

class B : public A
{
public:
    int add(int a, int b) override final {
        return a + b + 100;
    }
};

int main()
{
    A *a = new B();
    cout << a->add(1, 2) << endl;
    return 0;
}

 

发表于2018-07-09 18:44   修改于2018-07-09 18:44   评论:0   阅读:463  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo