c++11

c++的一些资料:

https://cpp.zeef.com/faraz.fallahi

语言核心

一、long long 类型

  int 型最大只能表示21亿多的大小,是不是经常感觉不够用?那么 long long 也许能满足你的需求,LINUX平台下它最大可以表示 9223372036854775807。这里简单提一下获取各个数值类型的方法(不同平台下得出结果可能会不同):

#include <limits.h>
#include <iostream>

int main()
{
    std::cout<<CHAR_MIN<<std::endl;
    std::cout<<CHAR_MAX<<std::endl;
    std::cout<<SHRT_MIN<<std::endl;
    std::cout<<SHRT_MAX<<std::endl;
    std::cout<<INT_MIN<<std::endl;
    std::cout<<INT_MAX<<std::endl;
    std::cout<<LLONG_MIN<<std::endl;
    std::cout<<LLONG_MAX<<std::endl;

    std::cout<<UCHAR_MAX<<std::endl;
    std::cout<<USHRT_MAX<<std::endl;
    std::cout<<UINT_MAX<<std::endl;
    std::cout<<ULLONG_MAX<<std::endl;
}

  我们看到这里引入的头文件实质上是C语言的头文件,LINUX下可能为 /usr/include/limits.h ,这是因为 C 语言早前就已经包含了 long long 类型了,当然你也可以引入c++的头文件 #include <climits> 来达成相同的效果。

 

 

二、列表初始化

int array[] = {1,2,3,4,5};

  c++可以像上面那样通过花括号的形式给数组初始化,但是却不能用同样的方式给 vector 初始化。在 c++11 中,这一点得到改善,且可以使用花括号的一致风格为变量或对象进行初始化。

#include <vector>

class User
{
    public:
        User(std::string _name):name(_name){}
        std::string name;
};

int main()
{
    std::vector<int> vect = {1,2,3,4,5};
    User my = {"yugd"};
}

 

 

三、nullptr

  设置空指针有三种方法,置为 0 或 NULL(预处理变量,实质上还是0) 或 nullptr。

  因为 0 存在多义性,比如经典的分别使用指针和数值型重载的函数,当传入0时,就会出现二义性,此时为明确调用指针型的重载,最好传入 (void*)0 ,如果要明确调用INT型的重载,最好传入 int(0)。(如 jsoncpp 库中 Value.h 文件中的 Value &operator[]( const char *key ); 和  Value &operator[]( UInt index ); ) 所以使用 nullptr 会更清晰直观。

 

 

 

四、enum class

  从字面上可以叫 "枚举类" ,俗称 "强类型枚举" ,英文一般叫 "scoped enums" ,它弥补了一些旧式枚举带来的问题:

1、旧式枚举可以隐式转换成 int,意味着枚举与 int 值、枚举与枚举之间可以进行比较(而这通常是不合理的)。强类型枚举则需要强制转换成 int 型,增加了类型安全。

2、旧式枚举因为没有 "界限" 的概念,通过枚举字段直接访问,所以不同枚举不能定义相同名字的枚举字段。在一个大型项目中,这是个比较蛋疼的事。比如这样编译时会报 SUCCESS 重定义:

enum Buy
{
    SUCCESS,
    MONEY_NOT_ENOUGH,
};

enum Sell
{
    SUCCESS,
    FAILD,
};

  此时可以使用这样的方法避免该问题:

#include <iostream>

struct Buy
{
    enum
    {
        SUCCESS = 1001,
        MONEY_NOT_ENOUGH = 1002,
    };
};

struct Sell
{
    enum
    {
        SUCCESS = 2001,
        FAILD = 2002,
    };
};

int main()
{
    std::cout<<Buy::SUCCESS<<std::endl;
    std::cout<<Sell::SUCCESS<<std::endl;
}

  但更好的方法是直接使用 enum class。

3、enum class 可以为枚举元素指定类型,如果不指定则默认是 int(但依然不能直接隐式转化成 int),如:

enum class Buy : unsigned int
{
    SUCCESS,
    MONEY_NOT_ENOUGH,
};

  此特性使得编译器可以确定枚举参数所占空间的大小,这样 enum class 就可以像普通类一样进行前向声明了,这一点是旧式枚举无法做到的,此特性对于优化大项目的编译时间可能会非常有用。

五、override 与 final

  新增的继承控制关键字,override 用于修饰子类的成员方法,明确表示此方法重载了基类的相应方法,编译器会检查函数签名是否完全一致,若不一致将报错。可以避免在想要重载时因签名不匹配,导致事实上并非重载的情况。

  final 关键字有两个作用,一是修饰类,禁止该类被继承;二是修饰虚函数(此前只要基类中某成员函数为virtual,则子类重载的函数也自动为virtual函数,即使不用 virtual 修饰,所以只要愿意可以无限重载下去),禁止该虚函数被子类重载。

运行期表现强化:

1、右值引用

构造期表现强化:

可用性强化:

功能强化:

 

库的变更

一、std::function、std::bind 与 Lambda

std::function 类似于函数指针,但更为灵活,与之相关的是 std::bind 和 Lambda表达式,这两者返回的都是 std::function 对象,三者联系紧密,示例如下:

#include <iostream>
#include <string>
#include <functional>

int add(int i, int j)
{
    return i + j;
}

int sub(int i, int j)
{
    return i - j;
}

int main()
{
    //typedef std::function<int(int,int)> Func; //定义一个该函数对象的类型
    //Func func;    //定义一个该类型的函数对象
    std::function<int(int,int)> func;   //直接定义一个函数对象

    func = add;
    std::cout<<func(4,3)<<std::endl;        //7
    func = sub;
    std::cout<<func(4,3)<<std::endl;        //1

    //std::bind 返回的就是 std::function 对象,std::bind 中有几个占位符,返回的std::function 函数对象就有几个参数
    std::function<int(int)> func1 = std::bind(sub,4,3);
    std::cout<<func1(5)<<std::endl;         //1
    // std::function 函数对象可以多出无用参数
    std::function<int(int)> func1_ = std::bind(sub,4,3);
    std::cout<<func1_(5)<<std::endl;            //1
    //这一点应用很多,如cocos2d-x中使用std::bind来绑定点击处理函数,应该是传入 std::function<void(Ref*)> ,但实际可以这样写:btn->addClickEventListener(std::bind(&GameLayer::backScene, this));

    std::function<int(int)> func2 = std::bind(sub,4,std::placeholders::_1); //sub函数的第二个参数被占位为1号参数
    std::cout<<func2(3)<<std::endl;         //1

    std::function<int(int,int)> func3 = std::bind(sub,std::placeholders::_2,std::placeholders::_1); //sub函数第一个参数被占位为2号参数,第二个参数
被占位为1号参数,所以下面的输出不是 1 而是 -1
    std::cout<<func3(4,3)<<std::endl;       //-1

    //Lambda表达式与 std::bind 一样返回的是 std::function 函数对象
    std::function<int(int,int)> func4 = [](int i, int j){return i+j;};
    std::cout<<func4(4,3)<<std::endl;
}
原文地址:https://www.cnblogs.com/tianyajuanke/p/3952471.html