使用C++11的一點總結

      C++11已不是新鮮技術,但對於我來講,工做中用得還不夠多(前東家長時間使用gcc3.4.5,雖然去年升了4.8.2,但舊模塊維護仍是3.4.5居多;新東家用的是4.4.6,不能完整支持C++11,並且有內部有基礎庫早已支持了C++11 STL的部分功能),再加上本身的練習也寫得少,瞭解僅是幾點簡單的皮毛, 這裏對C++11學習總結一番,指望對他人以及將來的我有點技術知識索引上的幫助。
     首先,wiki是最全面的: https://en.wikipedia.org/wiki/C%2B%2B11,這是C++完整的新功能,我的使用的編譯器可能不完整支持,能夠看這個編譯器+版本對C++1X的支持狀況: http://en.cppreference.com/w/cpp/compiler_support
     而後,看英文不夠快,找一篇看起來比較全的中文總結(不全,仍是要看wiki): http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html

1、新特性簡介html

C++11以前被稱爲C++0x,由於本來計劃在2010年發佈,因此以前一些編譯器使用C++11的編譯參數是:-std=c++0x,後面使用:-std=c++11。C++11 設計的核心是:少改動語言,多改動基礎庫。
改動涉及到這幾點:支持多線程編程(增長了thread庫)、增強泛型編程(增長了hash容器、任意多個元素的tuple、bind函數、lambda函數)、統一初始化(以花括號調用構造函數)、性能(右值引用和move),其它stl庫(正則表達式、原子操做庫),另外還有一些語法糖的支持,如:default、delete定義(能夠在派生類中delete掉基類的public函數),裸字符串的定義、類非靜態成員變量直接賦值、nullptr、支持連續兩個右尖括號、後置返回類型、Range-based的for循環、構造函數能夠調用另外一個構造函數、override關鍵字用於發現虛函數的覆蓋錯誤、string literal.......。

2、部分經常使用新特性\庫ios

挑選幾個經常使用的記錄以下

一、統一初始化c++

 以前,我想初始化一個放着map對象的容器,須要這樣子:
std::vector<std::map<std::string, std::string> > a;
std::map<std::string, std::string> tmp;
tmp.insert(std::make_pair("1", "2"));
a.push_back(tmp);
如今,我能夠直接用大括號:
std::vector<std::map<std::string, std::string>> a{ { { "1", "2" } } }
注: 部分統一初始化要到gcc4.7以後才支持。

二、函數綁定和lambda正則表達式

函數綁定是基礎庫支持的,把一個函數轉換爲一個對象,在異步編程上用的不少(回調函數bind成一個對象,而後把對象交給異步工做完成的通知者,由它觸發異步回調調用)。
lambda語法,則能夠跟標準庫的算法配合使用,或者跟bind一塊兒用在異步編程上。
eg1: bind
class Work {
public:
 void do_work() {
    std::cout << "do work" << std::endl;
  }
};
int main() {
    Work work;
    auto bar = std::bind(&Work::do_work, &work);
    bar();
}
eg2:清除字符串中的'a'字符:
std::string tmp = "abcdefgdaaa";
tmp.erase(std::remove_if(tmp.begin(), tmp.end(), [](char x) {
        return x == 'a';
    }), tmp.end());
std::cout << tmp << std::endl;
lambda語法:
[capture](parameters)->return-type->{body}
[capture](parameters){body}
[] // 沒有定義任何變量。使用未定義變量會致使錯誤。
[x, &y] // x 以傳值方式傳入(默認),y 以引用方式傳入。
[&] // 任何被使用到的外部變量皆隱式地以引用方式加以使用。
[=] // 任何被使用到的外部變量皆隱式地以傳值方式加以使用。
[&, x] // x 顯示地以傳值方式加以使用。其他變量以引用方式加以使用。
[=, &z] // z 顯示地以引用方式加以使用。其他變量以傳值方式加以使用。
注:lambda須要gcc4.5以後才支持

三、直接給類成員變量設置默認值算法

Non-static data member initializers
eg:
class A {
public:
    A () {}
    explicit A(int new_value) : value(new_value) {}

    int get() {
        return value;
    }
private:
    int value = 5; // 支持直接寫默認值
};
注:至少須要gcc4.7

四、新增tuple類型編程

tuple類型在傳輸多種類型組成的數據時,能夠省去定義struct,並且能夠有任意多的成員。
eg:
std::tuple<std::string, std::string, std::string, int, int> record = std::make_tuple("a", "b", "c", 100, 200);
std::cout << std::get<0>(record) << std::endl;
std::cout << std::get<4>(record) << std::endl;
gcc4.4對tuple的支持不夠完整(不用使用const 字符賦值給string),須要gcc4.7以上才完善。

五、新增hash表promise

std::unordered_set
std::unordered_multiset
std::unordered_map
std::unordered_multimap
查找性能比set、map的要快。

六、新增多線程支持多線程

std::thread
std::async
std::promise,std::future,
要特別說明下promise、future的概念:
「主線程建立一個promise,將與promise關聯的future交給新的線程,新線程等待從promise獲取數據,主線程經過promise向指望設置值,新線程收到通知繼續往下走。」
這說明,promise/future是用於異步編程時,線程之間的同步的,有點像多線程編程下的event通知。
eg:
#include <iostream>
#include <functional>
#include <thread>
#include <future>
void show(std::future<int>& fut) {
    std::cout << "work thread:" << std::this_thread::get_id() << std::endl;
    int x = fut.get(); // 等待獲取到結果
    std::cout << x << std::endl;
}
int main(){
    std::cout << "main thread:" << std::this_thread::get_id() << std::endl;
    std::promise<int> promise;
    std::future<int> future = promise.get_future();
    std::thread work_thread(show, std::ref(future));
    std::this_thread::sleep_for(std::chrono::seconds(3));
    promise.set_value(10);
    work_thread.join();
    return 0;
}
注:promise/future至少須要gcc4.7才支持
擴展說明: 從上面的例子能夠看到,標準庫的promise/future不支持設置回調函數,須要本身經過get函數等待,這是異步調用者(主線程)主動的在等待通知,不像js能夠經過.then函數設置回調通知函數,調用者能夠被動的被調用。 因此,當前不能作到完全的異步編程(一個回調後面繼續跟着回調)。但.then 函數已經在規劃中,參見:
"With .then, instead of waiting for the result, a continuation is 「attached」 to the asynchronous operation, which is invoked when the result is ready. "
"do this, and when it is done, then do this, and when it is done, then do this..."
有then函數的好處是,咱們的代碼能夠實現完全的異步,以上面的例子爲例,我只要告訴future回調函數是xx,主線程就不用再等待,它能夠去作別的,當工做完成的時候,工做線程主動的去觸發回調函數xx的調用。
另外,boost已經有then的功能,
#include <iostream>
#include <string>

#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION

#include <boost/thread/future.hpp>

using namespace boost;

int main() {
    future<int> f1 = async([]() { return 123; });
    future<std::string> f2 = f1.then([](future<int> f) {
        std::cout << f.get() << std::endl; // here .get() won't block
        return std::string("sgfsdfs");
    });
}
部分公司使用boost,或者從boost裏借鑑future.then()的實現造了一個基礎庫,就能夠在代碼中實現 : do this, and when it is done, then do this, and when it is done, then do this ....

七、其它異步

(1)能夠定義一個無需轉義的字符串,如:std::string b = R"x(c:\abc)" yy l)x";
其中x(是一個標識符,x能夠任意,最長16個字符。
注意:Raw string literals至少須要gcc4.4
(2)正則表達式庫
(3)構造函數委託
(4)std::shared_ptr 智能指針
(5)railing-return-type 後置返回類型
 
本文所在:http://www.cnblogs.com/cswuyg/p/6220671.html
 
學習參考:
相關文章
相關標籤/搜索