目前关于c++比较权威和官方的api文档可以参考CPP Reference,多阅读官方介绍可以少走很多坑和理解很多特性和设计。
boost和c++14提供了optional用于表示一个对象的未初始化状态,可以用作返回值或者参数传入,optional提供了统一的none代表未初始化状态,避免了使用magic value。std::optional<T> 可以和类型T一样进行赋值,例如:
#include <optional> std::optional<int> opt_a = 10 ; opt_a = 5 ; //change opt_a to 5 ;同样,如果你使用optional作为函数传入对象,也可以直接使用对应的对象直接调用函数,但注意,这样会调用拷贝构造函数!即进行深拷贝,上面代码段中的赋值操作也调用了拷贝构造函数。例如下述代码段:
#include <iostream> #include <optional> class MyInt{ public: int v ; int getv(){return v;} MyInt(int pv) { std::cout << "Constructor Called" << std::endl; v = pv;} MyInt(const MyInt& mi){ std::cout << "Copy Constructor Called" << std::endl; v = mi.v; } }; void funca(std::optional<MyInt> p){ std::cout << "funca call " << p->v << std::endl ; } int main() { MyInt a(5) ; funca(a) ; //auto Myint to optional<Myint>, Copy Constructor called. funca(5) ; //auto construct, constructor called return 0; }此外optional还支持直接构造,实现类似emplace_back的功能,避免额外构造一遍 上述代码的输出将会是:
Constructor Called Copy Constructor Called funca call 5 Constructor Called funca call 5同时std::optional中的type T必须是value type,即不支持引用类型,个人理解是你如果使用引用,代表该值不能为空,所以不提供这一操作。
c++ 也提供lambda表达式用于书写简介的代码段来完成重复的功能,或作为sort等函数的传入参数,使用非常方便。关于lambda表达式的使用有很多资料,在此只提醒两点
在进行外部捕获变量时显式指定,而不是默认全局捕获,这样可以提高代码的可读性(readbility),同时也避免别人在作用域添加了别的变量产生不必要的捕获lambda表达式应尽量简洁,在数行或者一个循环内完成,否则应定义单独的function,这也是为了提高可读性(readbility)c++中的map和unordered_map提供了[]和find两种方法来进行查询操作,这两者实际上是有区别的。使用[]进行查询时如果key不存在,则会插入key,而对应的value则会使用默认的构造函数进行构造。e.g.
std::unordered_map<string, string> dict ; std::string name = dict["lost"] ; //name will be "" mostly, but not sure...使用find时我们可以通过dict.find("key") != dict.end()判断key是否存在。 进一步的,find操作不会修改map的数据,是const的;相反,[] operator 则有可能修改,是非const的。由于[] operator的行为并不可控,且会自动插入数据,使用find是更安全的。关于[] operator 详细的介绍参考C++ Reference
numeric_limits 是c++ 标准库提供的数值类型的最大最小的值及其他特性介绍,可用于避免溢出(overfloat) 和用作初始值以及一些判定。提供了int, long, long long 等类型,详细参考CPP Reference
// numeric_limits example #include <iostream> // std::cout #include <limits> // std::numeric_limits int main () { std::cout << std::boolalpha; std::cout << "Minimum value for int: " << std::numeric_limits<int>::min() << '\n'; std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << '\n'; std::cout << "int is signed: " << std::numeric_limits<int>::is_signed << '\n'; std::cout << "Non-sign bits in int: " << std::numeric_limits<int>::digits << '\n'; std::cout << "int has infinity: " << std::numeric_limits<int>::has_infinity << '\n'; return 0; }