最近研究了一下现代C++的各种特性,发现语法糖还是非常好吃的,下面整理了一些常用的,还有一些很有趣的东西,可能有遗漏以后用到了再添加。

智能指针

C++11中最有用的估计就是智能指针了,加入标准之后再也不用去搬boost库了,一个shared_ptr就能解决。关于shared_ptr/weak_ptr/unique_ptr网上资料很多我就不复制了,这里写几个国内资料没有的:

  • shared_ptr从C++17起已经可以支持动态数组并且重载[]了,内置类型不需要提供删除器,比如扔个字符串进去是完全ok的,像这样:
    1
    2
    auto str = make_shared<char[]>(10);    // 据说将会在C++20资瓷
    shared_ptr<char> str(new char[10]);
    然后你就不需要管释放啦,内置类型会自动调用类似delete[]的东西释放掉,如果是你自定义的类数组还是需要指定删除器的,否则VS调试时会自动触发断点(微软爸爸好)。
    参考:https://stackoverflow.com/questions/43631415/using-shared-ptr-with-char

类型推断

autodecltype也是从C++11开始资瓷的,前者方便懒人,后者可能有各种神奇的用途。
之前你写个迭代器可能会变成这个鸟样子:

1
for(vector<int>::iterator i=v.begin();i!=v.end();++i)

这个代码不仅很丑(很长),而且如果没有代码提示之类的还容易拼错(手写代码了解一下23333),很显然别人通篇看到都是这个玩意肯定很头疼,即使你用typedef简化一下还是不爽,你一个实例就需要搞一个type,复制粘贴也是需要能量的!

现在你可以直接用auto代替vector<int>::iterator这种东西啦!是不是很爽?不过滥用auto也是会让人很不爽的而且可能会出BUG,我认为这样就失去了C系语言“类型明确”这个特点了,而且你看到的全是auto也不能迅速判断变量的类型,还要借助IDE才行,这是反人类的。

nullptr

增强程序健壮性的好东西,建议指针初始化或赋值抛弃NULL改用nullptr

for循环语法

类似其他语言foreach的语法糖,配合auto使用简直不要太爽,像这样:

1
2
3
int num[] = { 1,2,3,4,5 };
for (auto i : num)
cout << i << endl;

如果是STL,一般的遍历直接可以抛弃迭代器了,一个for (auto i : v)就可以遍历容器了对于简单的像“输出容器”这种操作很方便。

move语义

增强效率的东西,如果自写通用库(字符串、链表之类的)会用到,一般情况使用情况不多,除非对效率要求极高,你不用也是可以的,靠VS之类编译器优化已经可以做的很好了。

function和bind

这两个可以让函数指针之类的更加泛化(花哨),比如方便了类成员函数作为函数指针传入的各种操作,可以让回调函数的使用更加优(xuan)雅(ji)

lambda表达式

这也是一个千呼万唤始出来的东西,可以进行各种神奇操作,个人感觉最实在的就是不用另外开一个函数写各种cmp、deleter了,直接把lambda扔进参数就行了,让代码更加漂(nan)亮(dong)。

static_assert和模板类型推断

也是一个炫技和进行神奇操作的玩意儿,目前我应用的地方也就是一个泛型约束了,像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

template<class T>
class Base {
static_assert((is_same<T, int>::value) || (is_same<T, char>::value), "not int or char");
};

int main() {
Base<int> a; // ok
Base<char> b; // ok
Base<double> c; // compile error!
return 0;
}

可以看到我们约束了模板只对int和char有效,如果你试图实例化为double就会触发一个编译错误,很不错。

奇技淫巧

get/set自动生成

不像微软儿子C#,很轻松就可以写一个变量的set/get函数,C++中你只能一个一个加,这绝对不能忍。经过尝试发现可以通过宏定义来实现一条龙服务:

1
2
3
4
5
6
#define ClassVar(permission, type, name, value, funcname)       \
public: \
void Set##funcname(type v_val) { name = v_val; } \
type Get##funcname() const { return name; } \
permission: \
type name = value;

使用例子:

1
ClassVar(private, int, cnt_, 0, Count)

会生成

1
2
3
4
5
public:
void SetCount(int v_val) { cnt_ = v_val; }
int GetCount() const { return cnt_; }
private:
int cnt_ = 0;