c++11強化知識點

初始化列表(std::initializer_list)

  • c++11提供了std::initializer_list,將使得類對象的初始化也可以和普通數組或者POD數據一樣使用初始化列表的方式。只要爲類對象提供初始化列表構造函數即可。
  • std::initializer_list也可以作爲函數的參數使用。
  • 初始化列表std::initializer_list相關示例代碼如下。
#include <iostream>
#include <initializer_list>
#include <vector>

using namespace std;

class InitClass {
public:
    InitClass(initializer_list<int> list) {
        for (int l : list)
            initializer_list_.emplace_back(l);
    }

    void PrintInit() {
        for (int l : initializer_list_)
            cout << l << endl;
    }

    void Print(initializer_list<int> list) {
        for (int l : list)
            cout << l << endl;
    }

private:
    vector<int> initializer_list_;
};

struct A {
    double a;
    int b;
};
struct B {
    B(int a, double b): a_(a), b_(b) {}
private:
    int a_;
    double b_;
};


int main()
{
    // 使用初始化列表初始化類對象
    InitClass i = {1, 2, 3, 4, 5};
    i.PrintInit();
    cout << endl;
    // 初始化列表做函數參數
    i.Print({1, 2, 3});
    // 使用初始化列表初始化POD數據
    vector<int> v = {1, 2, 3, 4};
    A a {1.1, 1};
    B b {2, 2.2};
    
    return 0;
}

變長參數模板(typename... Args)

  • c++11提供了變長參數模板,堪比黑魔法。可以實現任意類型、任意個數的變長參數模板類和函數。
  • 可以使用經典的遞歸模板函數的方式去取出變長參數模板函數中的參數,示例代碼如下。
#include <iostream>
template<typename T>
void printf(T value) {
    std::cout << value << std::endl;
}
template<typename T, typename... Args>
void printf(T value, Args... args) {
    std::cout << value << std::endl;
    printf(args...);
}
int main() {
    printf(1, 2, "123", 1.1);
    return 0;
}
  • c++14提供了更簡便的方法,可以使用初始化列表展開變長參數,示例代碼如下。
// 編譯這個代碼需要開啓 -std=c++14
#include <iostream>
template<typename T, typename... Args>
auto print(T value, Args... args) {
    std::cout << value << std::endl;
    return std::initializer_list<T>{([&] {
        std::cout << args << std::endl;
    }(), value)...};
}
int main() {
    print(1, 2.1, "123");
    return 0;
}

強類型枚舉(enum class)

  • c++11提供了類型安全的枚舉類enum class。枚舉類中定義的枚舉值不能夠被隱式轉換爲整數,也不能與整數直接比較,更不能與不同的枚舉類型的枚舉值比較。
  • 枚舉類定義的枚舉值可以定義相同的值。
  • 枚舉類中可以自己定義枚舉值的類型,默認是int。
  • 可以通過重載<<運算符來實現直接打印枚舉類的值。
  • 可以定義模板轉換函數來方便將枚舉類的枚舉值與基本數據類型(如int)直接進行比較。
  • 所有示例代碼如下。
#include <iostream>
enum class new_enum : unsigned int {
    value1,
    value2,
    value3 = 888,
    value4 = 888
};

template<typename T>
std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e) {
    return stream << static_cast<typename std::underlying_type<T>::type>(e);
}

template<typename T>
auto to_underlying_type(const T& e) {
    return static_cast<typename std::underlying_type<T>::type>(e);
}

int main() {
    if (new_enum::value3 == new_enum::value4 && 888 == to_underlying_type(new_enum::value3))
    {
         std::cout << new_enum::value3 << std::endl;
    }
    return 0;
}

函數對象包裝器(std::function)

  • c++11提供了可以定義任意可調用類型的函數對象包裝器(std::function),這是對函數對象的一種類型安全的包裝。
  • 利用std::function和c++11提供的更強大的using語法以及Lambda函數,我們可以更方便的實現類對象中的簡單的回調函數。示例代碼如下。
#include <iostream>
#include <memory>

class A {
public:
    using CallBack = std::function<void()>;

    void SetCallBack(CallBack cb) { call_back_ = cb; }
    void CallCallBack() {
        if (call_back_)
        {
            call_back_();
        }
        
    }

private:
    CallBack call_back_ = nullptr;
};

class B {
public:
    B() {
        a = std::make_shared<A>();
        a->SetCallBack([](){
            std::cout << "call A cb in B" << std::endl;
        });
        a->CallCallBack();
    }

private:
    std::shared_ptr<A> a = nullptr;
};

int main() {
    B b;
}
  • 如果回調函數很複雜,不適合用Lambda函數實現,也可以通過std::bind來將回調函數綁定到類的成員函數上。

智能指針初始化(make_unique)

  • 爲了簡化c++的指針管理,c++11擴展了標準庫,推出了智能指針——std::shared_ptr/std::unique_ptr/std::weak_ptr。智能指針使用引用計數的方式來實現自動釋放資源,使得c++語言更具現代性。
  • 標準庫提供了std::make_shared來初始化一個std::shared_ptr,避免了我們使用new來初始化std::shared_ptr。但是由於“被標準委員會忘記了”,標準庫卻沒有提供make_unique的方法來給我們初始化一個std::unique_ptr(好在c++14提供了)。爲此我們可以自己實現一個make_unique,代碼如下。
#include <memory>

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args ) {
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

int main() {
    std::unique_ptr<int> p = make_unique<int>(1);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章