记录篇-c++11-开发小技巧

前言

本文是记录个人对c++11新特性的学习,文中所用可能会采用其他大神的图、思路、例子等,请大神们见谅。本博客文章是在学习过程的一些总结,整理出来,分享给大家,希望对各位读者有帮助,文章中的总结可能存在很多不完整或有错误的地方,也希望读者指出。

1、类成员初始化列表

 class A
 {
 public:
     //在 C++11中可以使用大括号语法初始化数组类型的成员变量
     A() : arr{0}
     {
     }
 
 public:
     int arr[4];
 };

 class A
 {
 public:
     //C++ 11 在类定义处初始化成员变量
     bool ma{true};
     int mb{2019};
     std::string mc{"helloworld"};
 };

2、final、 override 关键字和 =default、 =delete 语法

 class A final  //防止类被继承
 {
 };
 
 class B : A  //报编译错误
 {
 };

override:显式标记表明该方法重写了父类的同名方法,加了该关键字后,编译器会在编译阶段做相应的检查,如果其父类不存在相同签名格式的类方法,编译器就会给出相应的错误提示。

 //a.h
 //使用=default 标记这类函数,则编译器会给出默认的实现
 class A
 {
 public:
     A() = default; //如果构造和析构中没有需要实现的内容,则加=default。
     ~A() = default;
 };
 
 //a.cpp
 #include "a.h"
 //在 cpp 文件中就不用再写 A 的构造函数和析构函数的实现了
 class A
 {
 public:
     A() = default;
     ~A() = default;
 public:
     A(const A& a) = delete;
     A& operator =(const A& a) = delete; // 禁止编译器生成这些函数,实现防止这些类被拷贝
 };
 
 int main()
 {
     A a1;
     //A a2(a1);
     A a3;
     //a3 = a1;
     return 0;
 }
 //在 C++ 98/03 规范中, 如果我们想让一个类不能被拷贝(即不能调用其拷贝构造函数),则可以将其拷贝构造函数和 operator=函数定义成 private

3、STL中的emplace

emplace方便之处在于,可以用函数参数自动构造对象,而不是向vector的push_back,map的insert那样传入一个构造好的对象;
新引入的的三个成员emlace_front、empace 和 emplace_back,这些操作构造而不是拷贝元素到容器中,这些操作分别对应push_front、insert 和push_back,允许我们将元素放在容器头部、一个指定的位置和容器尾部

//C++11之前stl操作写法
std::vector<Point> vp;
std::map<std::string, Point> mp;

Point p(1, 2);
vp.push_back(p);
vp.push_back(Pointer(3, 4));

Point p1(10, 20);
mp.insert(std::pair<std::string, Point>("key1", p1));
Point p2(100, 200);
mp.insert(std::make_pair("key2", p2));

//C++11之后stl操作的写法
std::vector<Point> vp;
std::map<std::string, Point> mp;

vp.emplace_back(1, 2);
vp.emplace_back(3, 4);

Point p1(10, 20);
Point p2(100, 200);
mp.emplace("key1", p1);
mp.emplace("key2", p2);

与insert相比,省去了构造临时对象,减少了内存开销,但传递给emplace函数的参数必须与元素类型的构造函数相匹配。

4、using替换冗余的类型,尤其是std::function类型

class FuncFactory {
public:
    void put_func(std::string, std::function<std::vector<std::string>(std::string)>);
    std::function<std::vector<std::string>(std::string)> get_func(std::string);
private:
    std::unordered_map<std::string, std::function<std::vector<std::string>(std::string)>> _func_map;
};
using func_t = std::function<std::vector<std::string>(std::string)>;

class FuncFactory {
public:
    void put_func(std::string, func_t);
    func_t get_func(std::string);
private:
    std::unordered_map<std::string, func_t> _func_map;
};

5、头文件中使用#pragma once替换老破旧#ifndef #define #endif

pragma是基于头文件的文件路径来保持唯一的。而宏可以做到跨多个文件来保持include的唯一性。比如当你一个代码库中存在一个头文件的多个版本

6、用do while或IIFE跳过部分连续逻辑,但不结束函数

IIFE(Immediately Invoked Function Expression),即立即调用函数表达式

[]() {
    // 步骤1
    ...
    if (步骤1失败) {
        return;
    }
    // 步骤2
    ...
    if (步骤2失败) {
        return;
    }
    // 步骤3
    ...
    if (步骤3失败) {
        return;
    }
}();

// 步骤4
...
// 步骤5
...

普通 lambda表达式的末尾加上了一个括号,是让定义的lambda可以立即执行

7、函数直接返回STL容器或对象。不要返回指针,也不需要给函数加出参

std::vector<std::string> split(std::string str, std:string del) {
    std::vector<std::string> str_list;
    // ...
    return str_list;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值