精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

C++開發者都應該使用的10個C++11特性

開發 后端
在C++11新標準中,語言本身和標準庫都增加了很多新內容,本文只涉及了一些皮毛。不過我相信這些新特性當中有一些,應該成為所有C++開發者的 常規裝備。你也許看到過許多類似介紹各種C++11特性的文章。下面是我總結的,C++開發者都需要學習和使用的C++11新特性。

在C++11新標準中,語言本身和標準庫都增加了很多新內容,本文只涉及了一些皮毛。不過我相信這些新特性當中有一些,應該成為所有C++開發者的 常規裝備。你也許看到過許多類似介紹各種C++11特性的文章。下面是我總結的,C++開發者都需要學習和使用的C++11新特性。

auto

在C++11之前,auto關鍵字用來指定存儲期。在新標準中,它的功能變為類型推斷。auto現在成了一個類型的占位符,通知編譯器去根據初始化 代碼推斷所聲明變量的真實類型。各種作用域內聲明變量都可以用到它。例如,名空間中,程序塊中,或是for循環的初始化語句中。

  1. auto i = 42;        // i is an int 
  2. auto l = 42LL;      // l is an long long 
  3. auto p = new foo(); // p is a foo* 

使用auto通常意味著更短的代碼(除非你所用類型是int,它會比auto少一個字母)。試想一下當你遍歷STL容器時需要聲明的那些迭代器(iterator)。現在不需要去聲明那些typedef就可以得到簡潔的代碼了。

  1. std::map<std::string, std::vector<int>> map; 
  2. for(auto it = begin(map); it != end(map); ++it) 

需要注意的是,auto不能用來聲明函數的返回值。但如果函數有一個尾隨的返回類型時,auto是可以出現在函數聲明中返回值位置。這種情況下,auto 并不是告訴編譯器去推斷返回類型,而是指引編譯器去函數的末端尋找返回值類型。在下面這個例子中,函數的返回值類型就是operator+操作符作用在 T1、T2類型變量上的返回值類型。

  1. template <typename T1, typename T2> 
  2. auto compose(T1 t1, T2 t2) -> decltype(t1 + t2) 
  3.    return t1+t2; 
  4. auto v = compose(2, 3.14); // v's type is double 

nullptr

以前都是用0來表示空指針的,但由于0可以被隱式類型轉換為整形,這就會存在一些問題。關鍵字nullptr是std::nullptr_t類型的 值,用來指代空指針。nullptr和任何指針類型以及類成員指針類型的空值之間可以發生隱式類型轉換,同樣也可以隱式轉換為bool型(取值為 false)。但是不存在到整形的隱式類型轉換。

  1. void foo(int* p) {} 
  2.   
  3. void bar(std::shared_ptr<int> p) {} 
  4.   
  5. int* p1 = NULL; 
  6. int* p2 = nullptr;   
  7. if(p1 == p2) 
  8.   
  9. foo(nullptr); 
  10. bar(nullptr); 
  11.   
  12. bool f = nullptr; 
  13. int i = nullptr; // error: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type 

為了向前兼容,0仍然是個合法的空指針值。

Range-based for loops (基于范圍的for循環)

為了在遍歷容器時支持”foreach”用法,C++11擴展了for語句的語法。用這個新的寫法,可以遍歷C類型的數組、初始化列表以及任何重載了非成員的begin()和end()函數的類型。

如果你只是想對集合或數組的每個元素做一些操作,而不關心下標、迭代器位置或者元素個數,那么這種foreach的for循環將會非常有用。

  1. std::map<std::string, std::vector<int>> map; 
  2. std::vector<int> v; 
  3. v.push_back(1); 
  4. v.push_back(2); 
  5. v.push_back(3); 
  6. map["one"] = v; 
  7.   
  8. for(const auto& kvp : map) 
  9.   std::cout << kvp.first << std::endl; 
  10.   
  11.   for(auto v : kvp.second) 
  12.   { 
  13.      std::cout << v << std::endl; 
  14.   } 
  15.   
  16. int arr[] = {1,2,3,4,5}; 
  17. for(int& e : arr) 
  18.   e = e*e; 
  19.  
  20. C++ 11 CPP 11 features 

#p#

Override和final

我總覺得 C++中虛函數的設計很差勁,因為時至今日仍然沒有一個強制的機制來標識虛函數會在派生類里被改寫。vitual關鍵字是可選的,這使得閱讀代碼變得很費勁。因為可能需要追溯到繼承體系的源頭才能確定某個方法是否是虛函數。為了增加可讀性,我總是在派生類里也寫上virtual關鍵字,并且也鼓勵大家都這么做。即使這樣,仍然會產生一些微妙的錯誤。看下面這個例子:

  1. class B 
  2. public
  3.    virtual void f(short) {std::cout << "B::f" << std::endl;} 
  4. }; 
  5.   
  6. class D : public B 
  7. public
  8.    virtual void f(int) {std::cout << "D::f" << std::endl;} 
  9. }; 

D::f 按理應當重寫 B::f。然而二者的聲明是不同的,一個參數是short,另一個是int。因此D::f(原文為B::f,可能是作者筆誤——譯者注)只是擁有同樣名字 的另一個函數(重載)而不是重寫。當你通過B類型的指針調用f()可能會期望打印出D::f,但實際上則會打出 B::f 。

另一個很微妙的錯誤情況:參數相同,但是基類的函數是const的,派生類的函數卻不是。

  1. class B 
  2. public
  3.    virtual void f(intconst {std::cout << "B::f " << std::endl;} 
  4. }; 
  5.   
  6. class D : public B 
  7. public
  8.    virtual void f(int) {std::cout << "D::f" << std::endl;} 
  9. }; 

同樣,這兩個函數是重載而不是重寫,所以你通過B類型指針調用f()將打印B::f,而不是D::f。

幸運的是,現在有一種方式能描述你的意圖。新標準加入了兩個新的標識符(不是關鍵字)::

  1. override,表示函數應當重寫基類中的虛函數。
  2. final,表示派生類不應當重寫這個虛函數。

第一個的例子如下:

  1. class B 
  2. public
  3.    virtual void f(short) {std::cout << "B::f" << std::endl;} 
  4. }; 
  5.   
  6. class D : public B 
  7. public
  8.    virtual void f(int) override {std::cout << "D::f" << std::endl;} 
  9. }; 

現在這將觸發一個編譯錯誤(后面那個例子,如果也寫上override標識,會得到相同的錯誤提示):

  1. 'D::f' : method with override specifier 'override' did not override any base class methods 

另一方面,如果你希望函數不要再被派生類進一步重寫,你可以把它標識為final。可以在基類或任何派生類中使用final。在派生類中,可以同時使用override和final標識。

  1. class B 
  2. public
  3.    virtual void f(int) {std::cout << "B::f" << std::endl;} 
  4. }; 
  5.   
  6. class D : public B 
  7. public
  8.    virtual void f(int) override final {std::cout << "D::f" << std::endl;} 
  9. }; 
  10.   
  11. class F : public D 
  12. public
  13.    virtual void f(int) override {std::cout << "F::f" << std::endl;} 
  14. }; 

被標記成final的函數將不能再被F::f重寫。

Strongly-typed enums 強類型枚舉

傳統的C++枚舉類型存在一些缺陷:它們會將枚舉常量暴露在外層作用域中(這可能導致名字沖突,如果同一個作用域中存在兩個不同的枚舉類型,但是具有相同的枚舉常量就會沖突),而且它們會被隱式轉換為整形,無法擁有特定的用戶定義類型。

在C++11中通過引入了一個稱為強類型枚舉的新類型,修正了這種情況。強類型枚舉由關鍵字enum class標識。它不會將枚舉常量暴露到外層作用域中,也不會隱式轉換為整形,并且擁有用戶指定的特定類型(傳統枚舉也增加了這個性質)。

  1. enum class Options {None, One, All}; 
  2. Options o = Options::All; 

#p#

Smart Pointers 智能指針

已經有成千上萬的文章討論這個問題了,所以我只想說:現在能使用的,帶引用計數,并且能自動釋放內存的智能指針包括以下幾種:

  • unique_ptr: 如果內存資源的所有權不需要共享,就應當使用這個(它沒有拷貝構造函數),但是它可以轉讓給另一個unique_ptr(存在move構造函數)。
  • shared_ptr:  如果內存資源需要共享,那么使用這個(所以叫這個名字)。
  • weak_ptr: 持有被shared_ptr所管理對象的引用,但是不會改變引用計數值。它被用來打破依賴循環(想象在一個tree結構中,父節點通過一個共享所有權的引 用(chared_ptr)引用子節點,同時子節點又必須持有父節點的引用。如果這第二個引用也共享所有權,就會導致一個循環,最終兩個節點內存都無法釋 放)。

另一方面,auto_ptr已經被廢棄,不會再使用了。

什么時候使用unique_ptr,什么時候使用shared_ptr取決于對所有權的需求,我建議閱讀以下的討 論:http://stackoverflow.com/questions/15648844/using-smart-pointers-for- class-members

以下第一個例子使用了unique_ptr。如果你想把對象所有權轉移給另一個unique_ptr,需要使用std::move(我會在最后幾段討論這個函數)。在所有權轉移后,交出所有權的智能指針將為空,get()函數將返回nullptr。

  1. void foo(int* p) 
  2. std::cout << *p << std::endl; 
  3. std::unique_ptr<int> p1(new int(42)); 
  4. std::unique_ptr<int> p2 = std::move(p1); // transfer ownership 
  5.   
  6. if(p1) 
  7. foo(p1.get()); 
  8.   
  9. (*p2)++; 
  10.   
  11. if(p2) 
  12. foo(p2.get()); 

第二個例子展示了shared_ptr。用法相似,但語義不同,此時所有權是共享的。

  1. void foo(int* p) 
  2. void bar(std::shared_ptr<int> p) 
  3. ++(*p); 
  4. std::shared_ptr<int> p1(new int(42)); 
  5. std::shared_ptr<int> p2 = p1; 
  6.   
  7. bar(p1); 
  8. foo(p2.get()); 

第一個聲明和以下這行是等價的:

  1. auto p3 = std::make_shared<int>(42); 

make_shared<T>是一個非成員函數,使用它的好處是可以一次性分配共享對象和智能指針自身的內存。而顯示地使用 shared_ptr構造函數來構造則至少需要兩次內存分配。除了會產生額外的開銷,還可能會導致內存泄漏。在下面這個例子中,如果seed()拋出一個 錯誤就會產生內存泄漏。

  1. void foo(std::shared_ptr<int> p, int init) 
  2. *p = init; 
  3. foo(std::shared_ptr<int>(new int(42)), seed()); 

如果使用make_shared就不會有這個問題了。第三個例子展示了weak_ptr。注意,你必須調用lock()來獲得被引用對象的shared_ptr,通過它才能訪問這個對象。

  1. auto p = std::make_shared<int>(42); 
  2. std::weak_ptr<int> wp = p; 
  3.   
  4. auto sp = wp.lock(); 
  5. std::cout << *sp << std::endl; 
  6.   
  7. p.reset(); 
  8.   
  9. if(wp.expired()) 
  10. std::cout << "expired" << std::endl; 

如果你試圖鎖定(lock)一個過期(指被弱引用對象已經被釋放)的weak_ptr,那你將獲得一個空的shared_ptr.

Lambdas

匿名函數(也叫lambda)已經加入到C++中,并很快異軍突起。這個從函數式編程中借來的強大特性,使很多其他特性以及類庫得以實現。你可以在 任何使用函數對象或者函子(functor)或std::function的地方使用lambda。你可以從這里 (http://msdn.microsoft.com/en-us/library/dd293603.aspx)找到語法說明。

  1. std::vector<int> v; 
  2. v.push_back(1); 
  3. v.push_back(2); 
  4. v.push_back(3); 
  5.   
  6. std::for_each(std::begin(v), std::end(v), [](int n) {std::cout << n << std::endl;}); 
  7.   
  8. auto is_odd = [](int n) {return n%2==1;}; 
  9. auto pos = std::find_if(std::begin(v), std::end(v), is_odd); 
  10. if(pos != std::end(v)) 
  11. std::cout << *pos << std::endl; 

#p#

更復雜的是遞歸lambda。考慮一個實現Fibonacci函數的lambda。如果你試圖用auto來聲明,就會得到一個編譯錯誤。

  1. auto fib = [&fib](int n) {return n < 2 ? 1 : fib(n-1) + fib(n-2);};
  1. error C3533: 'auto &': a parameter cannot have a type that contains 'auto' 
  2. error C3531: 'fib': a symbol whose type contains 'auto' must have an initializer 
  3. error C3536: 'fib': cannot be used before it is initialized 
  4. error C2064: term does not evaluate to a function taking 1 arguments 

問題出在auto意味著對象類型由初始表達式決定,然而初始表達式又包含了對其自身的引用,因此要求先知道它的類型,這就導致了無窮遞歸。解決問題的關鍵就是打破這種循環依賴,用std::function顯式的指定函數類型:

  1. std::function<int(int)> lfib = [&lfib](int n) {return n < 2 ? 1 : lfib(n-1) + lfib(n-2);}; 

非成員begin()和end()

也許你注意到了,我在前面的例子中已經用到了非成員begin()和end()函數。他們是新加入標準庫的,除了能提高了代碼一致性,還有助于更多 地使用泛型編程。它們和所有的STL容器兼容。更重要的是,他們是可重載的。所以它們可以被擴展到支持任何類型。對C類型數組的重載已經包含在標準庫中 了。

我們還用上一個例子中的代碼來說明,在這個例子中我打印了一個數組然后查找它的第一個偶數元素。如果std::vector被替換成C類型數組。代碼可能看起來是這樣的:

  1. int arr[] = {1,2,3}; 
  2. std::for_each(&arr[0], &arr[0]+sizeof(arr)/sizeof(arr[0]), [](int n) {std::cout << n << std::endl;}); 
  3.   
  4. auto is_odd = [](int n) {return n%2==1;}; 
  5. auto begin = &arr[0]; 
  6. auto end = &arr[0]+sizeof(arr)/sizeof(arr[0]); 
  7. auto pos = std::find_if(begin, end, is_odd); 
  8. if(pos != end) 
  9. std::cout << *pos << std::endl; 

如果使用非成員的begin()和end()來實現,就會是以下這樣的:

  1. int arr[] = {1,2,3}; 
  2. std::for_each(std::begin(arr), std::end(arr), [](int n) {std::cout << n << std::endl;}); 
  3.   
  4. auto is_odd = [](int n) {return n%2==1;}; 
  5. auto pos = std::find_if(std::begin(arr), std::end(arr), is_odd); 
  6. if(pos != std::end(arr)) 
  7. std::cout << *pos << std::endl; 

這基本上和使用std::vecto的代碼是完全一樣的。這就意味著我們可以寫一個泛型函數處理所有支持begin()和end()的類型。

  1. template <typename Iterator> 
  2. void bar(Iterator begin, Iterator end) 
  3. std::for_each(begin, end, [](int n) {std::cout << n << std::endl;}); 
  4.   
  5. auto is_odd = [](int n) {return n%2==1;}; 
  6. auto pos = std::find_if(begin, end, is_odd); 
  7. if(pos != end) 
  8. std::cout << *pos << std::endl; 
  9.   
  10. template <typename C> 
  11. void foo(C c) 
  12. bar(std::begin(c), std::end(c)); 
  13.   
  14. template <typename T, size_t N> 
  15. void foo(T(&arr)[N]) 
  16. bar(std::begin(arr), std::end(arr)); 
  17.   
  18. int arr[] = {1,2,3}; 
  19. foo(arr); 
  20.   
  21. std::vector<int> v; 
  22. v.push_back(1); 
  23. v.push_back(2); 
  24. v.push_back(3); 
  25. foo(v); 

static_assert和 type traits

static_assert提供一個編譯時的斷言檢查。如果斷言為真,什么也不會發生。如果斷言為假,編譯器會打印一個特殊的錯誤信息。

  1. template <typename T, size_t Size> 
  2. class Vector 
  3.    static_assert(Size < 3, "Size is too small"); 
  4.    T _points[Size]; 
  5. }; 
  6.   
  7. int main() 
  8.    Vector<int, 16> a1; 
  9.    Vector<double, 2> a2; 
  10.    return 0; 
  11. }
  1. error C2338: Size is too small 
  2. see reference to class template instantiation 'Vector<T,Size>' being compiled 
  3.    with 
  4.    [ 
  5.       T=double
  6.       Size=2 
  7.    ] 

#p#

static_assert和type traits一起使用能發揮更大的威力。type traits是一些class,在編譯時提供關于類型的信息。在頭文件<type_traits>中可以找到它們。這個頭文件中有好幾種 class: helper class,用來產生編譯時常量。type traits class,用來在編譯時獲取類型信息,還有就是type transformation class,他們可以將已存在的類型變換為新的類型。

下面這段代碼原本期望只做用于整數類型。

  1. template <typename T1, typename T2> 
  2. auto add(T1 t1, T2 t2) -> decltype(t1 + t2) 
  3. return t1 + t2; 

但是如果有人寫出如下代碼,編譯器并不會報錯

  1. std::cout << add(1, 3.14) << std::endl; 
  2. std::cout << add("one", 2) << std::endl; 

程序會打印出4.14和”e”。但是如果我們加上編譯時斷言,那么以上兩行將產生編譯錯誤。

  1. template <typename T1, typename T2> 
  2. auto add(T1 t1, T2 t2) -> decltype(t1 + t2) 
  3.    static_assert(std::is_integral<T1>::value, "Type T1 must be integral"); 
  4.    static_assert(std::is_integral<T2>::value, "Type T2 must be integral"); 
  5.   
  6.    return t1 + t2; 
  7. }
  1. error C2338: Type T2 must be integral 
  2. see reference to function template instantiation 'T2 add<int,double>(T1,T2)' being compiled 
  3.    with 
  4.    [ 
  5.       T2=double
  6.       T1=int 
  7.    ] 
  8. error C2338: Type T1 must be integral 
  9. see reference to function template instantiation 'T1 add<const char*,int>(T1,T2)' being compiled 
  10.    with 
  11.    [ 
  12.       T1=const char *, 
  13.       T2=int 
  14.    ] 

Move semantics (Move語義)

這是C++11中所涵蓋的另一個重要話題。就這個話題可以寫出一系列文章,僅用一個段落來說明顯然是不夠的。因此在這里我不會過多的深入細節,如果你還不是很熟悉這個話題,我鼓勵你去閱讀更多地資料。

C++11加入了右值引用(rvalue reference)的概念(用&&標識),用來區分對左值和右值的引用。左值就是一個有名字的對象,而右值則是一個無名對象(臨時對 象)。move語義允許修改右值(以前右值被看作是不可修改的,等同于const T&類型)。

C++的class或者struct以前都有一些隱含的成員函數:默認構造函數(僅當沒有顯示定義任何其他構造函數時才存在),拷貝構造函數,析構 函數還有拷貝賦值操作符。拷貝構造函數和拷貝賦值操作符提供bit-wise的拷貝(淺拷貝),也就是逐個bit拷貝對象。也就是說,如果你有一個類包含 指向其他對象的指針,拷貝時只會拷貝指針的值而不會管指向的對象。在某些情況下這種做法是沒問題的,但在很多情況下,實際上你需要的是深拷貝,也就是說你 希望拷貝指針所指向的對象。而不是拷貝指針的值。這種情況下,你需要顯示地提供拷貝構造函數與拷貝賦值操作符來進行深拷貝。

如果你用來初始化或拷貝的源對象是個右值(臨時對象)會怎么樣呢?你仍然需要拷貝它的值,但隨后很快右值就會被釋放。這意味著產生了額外的操作開銷,包括原本并不需要的空間分配以及內存拷貝。

現在說說move constructor和move assignment operator。這兩個函數接收T&&類型的參數,也就是一個右值。在這種情況下,它們可以修改右值對象,例如“偷走”它們內部指針所 指向的對象。舉個例子,一個容器的實現(例如vector或者queue)可能包含一個指向元素數組的指針。當用一個臨時對象初始化一個對象時,我們不需 要分配另一個數組,從臨時對象中把值復制過來,然后在臨時對象析構時釋放它的內存。我們只需要將指向數組內存的指針值復制過來,由此節約了一次內存分配, 一次元數組的復制以及后來的內存釋放。

以下代碼實現了一個簡易的buffer。這個buffer有一個成員記錄buffer名稱(為了便于以下的說明),一個指針(封裝在unique_ptr中)指向元素為T類型的數組,還有一個記錄數組長度的變量。

#p#

  1. template <typename T> 
  2. class Buffer 
  3.    std::string          _name; 
  4.    size_t               _size; 
  5.    std::unique_ptr<T[]> _buffer; 
  6.   
  7. public
  8.    // default constructor 
  9.    Buffer(): 
  10.       _size(16), 
  11.       _buffer(new T[16]) 
  12.    {} 
  13.   
  14.    // constructor 
  15.    Buffer(const std::string& name, size_t size): 
  16.       _name(name), 
  17.       _size(size), 
  18.       _buffer(new T[size]) 
  19.    {} 
  20.   
  21.    // copy constructor 
  22.    Buffer(const Buffer& copy): 
  23.       _name(copy._name), 
  24.       _size(copy._size), 
  25.       _buffer(new T[copy._size]) 
  26.    { 
  27.       T* source = copy._buffer.get(); 
  28.       T* dest = _buffer.get(); 
  29.       std::copy(source, source + copy._size, dest); 
  30.    } 
  31.   
  32.    // copy assignment operator 
  33.    Buffer& operator=(const Buffer& copy) 
  34.    { 
  35.       if(this != ©) 
  36.       { 
  37.          _name = copy._name; 
  38.   
  39.          if(_size != copy._size) 
  40.          { 
  41.             _buffer = nullptr; 
  42.             _size = copy._size; 
  43.             _buffer = _size > 0 > new T[_size] : nullptr; 
  44.          } 
  45.   
  46.          T* source = copy._buffer.get(); 
  47.          T* dest = _buffer.get(); 
  48.          std::copy(source, source + copy._size, dest); 
  49.       } 
  50.   
  51.       return *this
  52.    } 
  53.   
  54.    // move constructor 
  55.    Buffer(Buffer&& temp): 
  56.       _name(std::move(temp._name)), 
  57.       _size(temp._size), 
  58.       _buffer(std::move(temp._buffer)) 
  59.    { 
  60.       temp._buffer = nullptr; 
  61.       temp._size = 0; 
  62.    } 
  63.   
  64.    // move assignment operator 
  65.    Buffer& operator=(Buffer&& temp) 
  66.    { 
  67.       assert(this != &temp); // assert if this is not a temporary 
  68.   
  69.       _buffer = nullptr; 
  70.       _size = temp._size; 
  71.       _buffer = std::move(temp._buffer); 
  72.   
  73.       _name = std::move(temp._name); 
  74.   
  75.       temp._buffer = nullptr; 
  76.       temp._size = 0; 
  77.   
  78.       return *this
  79.    } 
  80. }; 
  81.   
  82. template <typename T> 
  83. Buffer<T> getBuffer(const std::string& name) 
  84.    Buffer<T> b(name, 128); 
  85.    return b; 
  86. int main() 
  87.    Buffer<int> b1; 
  88.    Buffer<int> b2("buf2", 64); 
  89.    Buffer<int> b3 = b2; 
  90.    Buffer<int> b4 = getBuffer<int>("buf4"); 
  91.    b1 = getBuffer<int>("buf5"); 
  92.    return 0; 

默認的copy constructor以及copy assignment operator大家應該很熟悉了。C++11中新增的是move constructor以及move assignment operator,這兩個函數根據上文所描述的move語義實現。如果你運行這段代碼,你就會發現b4構造時,move constructor會被調用。同樣,對b1賦值時,move assignment operator會被調用。原因就在于getBuffer()的返回值是一個臨時對象——也就是右值。

你也許注意到了,move constuctor中當我們初始化變量name和指向buffer的指針時,我們使用了std::move。name實際上是一個 string,std::string實現了move語義。std::unique_ptr也一樣。但是如果我們寫_name(temp._name), 那么copy constructor將會被調用。不過對于_buffer來說不能這么寫,因為std::unique_ptr沒有copy constructor。但為什么std::string的move constructor此時沒有被調到呢?這是因為雖然我們使用一個右值調用了Buffer的move constructor,但在這個構造函數內,它實際上是個左值。為什么?因為它是有名字的——“temp”。一個有名字的對象就是左值。為了再把它變為 右值(以便調用move constructor)必須使用std::move。這個函數僅僅是把一個左值引用變為一個右值引用。

更新:雖然這個例子是為了說明如何實現move constructor以及move assignment operator,但具體的實現方式并不是唯一的。在本文的回復中Member 7805758同學提供了另一種可能的實現。為了方便查看,我把它也列在下面:

  1. template <typename T> 
  2. class Buffer 
  3.    std::string          _name; 
  4.    size_t               _size; 
  5.    std::unique_ptr<T[]> _buffer; 
  6.   
  7. public
  8.    // constructor 
  9.    Buffer(const std::string& name = ""size_t size = 16): 
  10.       _name(name), 
  11.       _size(size), 
  12.       _buffer(size? new T[size] : nullptr) 
  13.    {} 
  14.   
  15.    // copy constructor 
  16.    Buffer(const Buffer& copy): 
  17.       _name(copy._name), 
  18.       _size(copy._size), 
  19.       _buffer(copy._size? new T[copy._size] : nullptr) 
  20.    { 
  21.       T* source = copy._buffer.get(); 
  22.       T* dest = _buffer.get(); 
  23.       std::copy(source, source + copy._size, dest); 
  24.    } 
  25.   
  26.    // copy assignment operator 
  27.    Buffer& operator=(Buffer copy) 
  28.    { 
  29.        swap(*this, copy); 
  30.        return *this
  31.    } 
  32.   
  33.    // move constructor 
  34.    Buffer(Buffer&& temp):Buffer() 
  35.    { 
  36.       swap(*this, temp); 
  37.    } 
  38.   
  39.    friend void swap(Buffer& first, Buffer& second) noexcept 
  40.    { 
  41.        using std::swap; 
  42.        swap(first._name  , second._name); 
  43.        swap(first._size  , second._size); 
  44.        swap(first._buffer, second._buffer); 
  45.    } 
  46. }; 

結論

關于C++11還有很多要說的。本文只是各種入門介紹中的一個。本文展示了一系列C++開發者應當使用的核心語言特性與標準庫函數。然而我建議你能更加深入地學習,至少也要再看看本文所介紹的特性中的部分。

原文鏈接:http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer

譯文鏈接:http://blog.jobbole.com/44015/

 

責任編輯:陳四芳 來源: 伯樂在線
相關推薦

2019-05-24 09:04:31

C++編程語言開發

2018-10-16 11:03:19

API開發者AR

2019-11-23 23:38:51

開發者微服務安全

2023-11-27 15:49:55

軟件開發系統設計

2023-11-17 14:18:48

開發編程

2022-04-27 09:48:56

JS前端開發

2019-11-20 12:09:01

JavaScriptGitHub工具

2025-08-29 07:00:00

Go并發開發

2016-09-28 22:44:40

HttpWeb

2024-09-02 14:30:43

2013-06-26 09:42:52

Web開發URL編碼URL

2012-12-26 09:51:52

C++開發者C++ CX

2025-03-05 09:21:08

2023-08-11 18:11:49

2025-01-07 10:01:10

2018-05-03 08:45:58

Linux命令

2020-06-03 18:10:46

GitHub代碼庫前端

2023-04-17 19:23:10

字符串Bash

2021-03-09 10:26:24

Python開發工具

2025-01-20 09:10:00

C++C++11開發
點贊
收藏

51CTO技術棧公眾號

欧美三级电影在线| av在线二区| 国内在线观看一区二区三区| 精品黑人一区二区三区久久| 玩弄中年熟妇正在播放| 国产精品四虎| 国产一区二区在线电影| 97精品免费视频| ass极品国模人体欣赏| 精品一区二区三区在线观看视频| 亚洲国产视频网站| 亚洲bbw性色大片| www.热久久| 久久精品一区二区三区中文字幕| 久久精品99久久久久久久久| 久久久久成人精品无码中文字幕| 成人在线视频观看| 偷拍日韩校园综合在线| 一本一本a久久| 亚洲色偷精品一区二区三区| 国产在线播放一区| 日本欧美黄网站| 成人观看免费视频| 红桃成人av在线播放| 精品国产乱码久久久久久久| 国产又黄又猛又粗| 男女羞羞在线观看| 一区二区三区四区不卡视频| 亚洲v国产v在线观看| 亚洲春色一区二区三区| 久久精品国产一区二区三区免费看 | 91中文字幕在线播放| 国产欧美日韩亚洲一区二区三区| 久久福利视频导航| 国产精品免费无码| 日韩精品导航| 欧美成人精品3d动漫h| 亚洲视频第二页| 中文字幕一区久| 亚洲午夜激情av| 法国空姐在线观看免费| h视频在线免费| 91麻豆国产福利精品| 99在线热播| 99久久精品无免国产免费| 日本美女一区二区三区视频| 奇米四色中文综合久久| 日本中文字幕网| 亚洲人人精品| 久久久久久久一| 麻豆一区二区三区精品视频| 中文字幕免费一区二区| 久久精品视频导航| 亚洲一区电影在线观看| 欧美电影一区| 色777狠狠综合秋免鲁丝| 熟女俱乐部一区二区| 亚洲宅男一区| 亚洲天堂av女优| b站大片免费直播| 亚洲尤物av| 一本色道久久综合亚洲精品小说| 337人体粉嫩噜噜噜| 国产亚洲欧美日韩在线观看一区二区 | 欧美一级特黄a| 成人免费网站www网站高清| 色呦呦国产精品| 亚洲 中文字幕 日韩 无码| 亚洲va中文在线播放免费| 日韩欧美在线一区| 亚洲少妇第一页| 久久天天久久| 欧美一卡二卡在线| 国产精品成人免费一区久久羞羞| 哺乳一区二区三区中文视频| 亚洲精品美女在线观看| 波多野结衣办公室33分钟| 女优一区二区三区| 中文字幕av日韩| 日本福利片在线观看| 黄色在线一区| 国产成人精品免高潮在线观看| 免费av中文字幕| 精品综合久久久久久8888| 亚洲精品欧美日韩| 黄色一级大片在线免费看国产一| av男人天堂一区| 日韩精品久久久毛片一区二区| 亚洲麻豆精品| 亚洲国产另类精品专区| 欧美a在线视频| 亚洲国产天堂| 337p日本欧洲亚洲大胆精品| 精品无人区无码乱码毛片国产| 久久综合国产| 久久久久久久久久国产| 伊人久久久久久久久久久久| 国产乱码精品一区二区三区忘忧草 | 日本精品视频| 亚洲免费电影一区| 91人妻一区二区三区蜜臀| 日韩天堂av| 成人乱色短篇合集| 亚洲欧美色视频| 国产精品久久久久一区二区三区 | 日韩一区二区三| 亚洲熟妇无码av| 亚洲美女视频| 国产91色在线免费| 精品国产无码一区二区| 国产欧美一区二区在线观看| 国产a级黄色大片| 亚洲a∨精品一区二区三区导航| 欧美一区二区三区播放老司机| 一本加勒比波多野结衣| 日韩成人三级| 91精品国产高清自在线看超| 国产精品国产三级国产aⅴ| 91香蕉视频mp4| 欧美 日韩 国产精品| 精品欧美日韩精品| 亚洲精品国产综合区久久久久久久| av在线免费播放网址| 久久av一区| 国产98在线|日韩| 黄视频网站在线| 日本高清不卡aⅴ免费网站| 韩国三级在线看| 91免费精品| 国产精品mp4| 同心难改在线观看| 亚洲国产aⅴ成人精品无吗| 亚洲欧美天堂在线| 日韩极品一区| 国产精品国语对白| 黄色av网站在线| 天天操天天色综合| 丝袜熟女一区二区三区| 国自产拍偷拍福利精品免费一| 91精品免费视频| 日韩精品黄色| 欧美色图第一页| 无码人妻丰满熟妇啪啪欧美| 麻豆精品91| 玛丽玛丽电影原版免费观看1977| 国模私拍视频在线播放| 欧美一级国产精品| 欧美日韩色视频| 精品亚洲成a人| 综合色婷婷一区二区亚洲欧美国产| 欧亚一区二区| 中文字幕欧美国内| 一级黄色小视频| 自拍偷在线精品自拍偷无码专区 | 国产午夜福利片| 国产99一区视频免费| 黄色影视在线观看| 日韩在线精品强乱中文字幕| 欧美老女人性视频| 午夜久久久久久噜噜噜噜| 亚洲人一二三区| 女人扒开双腿让男人捅| 欧美三级午夜理伦三级中文幕| 99精品在线直播| 24小时免费看片在线观看| 亚洲国产日韩欧美在线图片| 国产一级18片视频| 国产亚洲综合在线| 另类小说色综合| 亚洲深深色噜噜狠狠爱网站| 国产高清自拍一区| 爱草tv视频在线观看992| 亚洲精品日韩久久久| 好吊色在线视频| 中文字幕av资源一区| 91丝袜超薄交口足| 激情丁香综合| 欧洲精品码一区二区三区免费看| 九色成人搞黄网站| 九九久久精品一区| 神马久久精品| 欧美精品丝袜中出| 久久久久久天堂| 91免费在线看| 在线观看免费的av| 亚洲午夜极品| 日韩久久在线| 国模大尺度视频一区二区| 欧美激情在线观看视频| 欧美在线观看在线观看| 91麻豆精品国产自产在线观看一区| 国产亚洲精久久久久久无码77777| 成人黄色网址在线观看| 久久久精品三级| 国产在线日韩| 日韩亚洲欧美精品| 久久在线观看| 国产国语videosex另类| h网站久久久| 亚洲欧美国产精品| 国产精品视频无码| 色综合色综合色综合色综合色综合| 少妇太紧太爽又黄又硬又爽小说| 大胆亚洲人体视频| 久久99999| 亚洲精品偷拍| 青青草影院在线观看| 日韩在线影视| 91精品国产高清久久久久久91裸体 | 国产精品不卡一区二区三区| 中文字幕三级电影| 国产在线视频精品一区| 欧美xxxxx在线视频| 国产精品久久久久久久久久10秀 | 国产精品嫩草影院一区二区 | 日本欧美黄网站| 牛牛精品在线| 久久精品夜夜夜夜夜久久| 男人天堂资源在线| 日韩美女视频在线| 亚洲无码精品国产| 色婷婷综合五月| 99精品视频99| 亚洲精品高清在线观看| 992在线观看| 久久尤物电影视频在线观看| 国产欧美视频一区| 国产又粗又猛又爽又黄91精品| 人妻无码视频一区二区三区| 99热精品在线| h无码动漫在线观看| 一区二区影院| 中文字幕一区二区三区5566| 精品午夜久久| 蜜桃视频成人| 日韩极品在线| 国产呦系列欧美呦日韩呦| 国产美女精品视频免费播放软件 | 青青青在线观看视频| 欧美一区二区性| 成人免费看片网站| 免费精品一区| 成人网址在线观看| 国产精品蜜月aⅴ在线| 国产成一区二区| 日韩在线影院| 欧美最近摘花xxxx摘花| 女海盗2成人h版中文字幕| 国外成人在线直播| av免费不卡| 91精品国产乱码久久久久久久久| 波多野结衣中文在线| 97超级碰碰碰久久久| 咪咪网在线视频| 68精品久久久久久欧美| 中文在线资源| 日韩av电影中文字幕| 亚洲成人人体| 国产黑人绿帽在线第一区| 精品国模一区二区三区| 国产精品黄页免费高清在线观看| 素人一区二区三区| 国产色视频一区| 国产一区二区在线观| 不卡视频一区二区| 国产毛片久久久| 蜜桃臀一区二区三区| 国产欧美一区二区精品久久久| 性高潮久久久久久久久| 亚洲天天影视网| 欧美在线一区视频| 久久精品一区二区三区中文字幕| 久久午夜夜伦鲁鲁一区二区| 美女视频黄频大全不卡视频在线播放| 最新国产黄色网址| 国产98色在线|日韩| 丰满大乳奶做爰ⅹxx视频| 国产天堂亚洲国产碰碰| 中文字幕乱码av| 亚洲一区二区视频| 在线免费黄色av| 欧美日韩电影在线| 懂色av一区二区三区四区 | 高h视频在线| 久久精品91久久久久久再现| 麻豆蜜桃在线| 日韩美女在线看| 97久久中文字幕| 国产精品播放| blacked蜜桃精品一区| 黄色影视在线观看| 新67194成人永久网站| 在线看免费毛片| 99re视频这里只有精品| 人妻互换一区二区激情偷拍| 一区二区三区.www| 欧美特级黄色片| 日韩精品一区二区三区三区免费| 青青国产在线| 欧美日韩福利电影| 色8久久影院午夜场| 97人摸人人澡人人人超一碰| 欧美猛男男男激情videos| 干日本少妇视频| 日本系列欧美系列| 人妻体内射精一区二区三区| 国产精品免费久久久久| 91精品国产高潮对白| 欧美美女视频在线观看| 亚洲卡一卡二卡三| 日韩一级黄色av| 欧美男女交配| 国产精品初高中精品久久| 精品国产一区二区三区久久久蜜臀| 日本久久久网站| 久久99精品久久久| 黄免费在线观看| 欧美日韩免费在线观看| 国产成人av免费看| 中文字幕成人精品久久不卡| 捆绑调教日本一区二区三区| 91在线观看免费高清| 日产午夜精品一线二线三线| 欧美 日韩精品| 丁香桃色午夜亚洲一区二区三区 | 亚洲激情成人在线| 国产又粗又猛又黄视频| 亚洲国产欧美一区| 在线视频国产区| 成人一区二区电影| 久久国产成人午夜av影院宅| 韩国一区二区av| 久久综合资源网| 国产成人在线免费视频| 亚洲第一av网| 青青在线视频| 91视频国产高清| 午夜国产一区二区| 中文久久久久久| 中文字幕第一区第二区| 伊人久久中文字幕| 亚洲性av在线| 精品欧美日韩精品| 天堂社区 天堂综合网 天堂资源最新版| 99精品热6080yy久久| 日韩免费高清一区二区| 亚洲成人激情自拍| 欧美少妇bbw| 久久人人97超碰精品888| 盗摄系列偷拍视频精品tp| www.亚洲成人网| aaa亚洲精品| wwwxxx亚洲| 亚洲欧美精品suv| 美女18一级毛片一品久道久久综合| 精品在线视频一区二区三区| 在线亚洲精品| 少妇饥渴放荡91麻豆| 丰满岳妇乱一区二区三区| 欧美美女搞黄| 国产精品美女网站| 91视频综合| 午夜激情视频网| 亚洲午夜精品一区二区三区他趣| 天天干视频在线观看| 日本亚洲欧美成人| 日本道不卡免费一区| 超碰在线资源站| 亚洲成人免费在线| 涩涩视频在线观看免费| 日本成人免费在线| 成人精品影院| 一级日本黄色片| 精品美女久久久久久免费| 国产三级在线免费观看| 国产日韩欧美成人| 一区二区中文字| 999精品免费视频| 欧美亚洲国产一区二区三区va | 亚洲精品综合在线| 亚洲 小说区 图片区 都市| 国产成人精品免高潮在线观看| 91亚洲国产| 亚洲精品乱码久久| 精品视频在线看| а√在线中文在线新版| 日韩久久在线| 成人永久看片免费视频天堂| 国产婷婷色一区二区在线观看| 中文欧美日本在线资源| 久久久久久久久久久久电影| 自慰无码一区二区三区| 国产精品久久久久婷婷| 亚洲精华国产精华精华液网站| 91av成人在线| 亚洲综合中文| 91视频免费观看网站| 综合激情五月婷婷| 青青在线视频免费观看| 久久亚洲一级片|