C++11語法糖


C++讀書筆記(牛客網)

 

1.constexpr變量:聲明為constexpr的變量一定是一個常量,新標准允許定義一種特殊的constexpr函數使得編譯時就可計算結果,這樣就能用constexpr函數去初始化constexpr變量。

2.類型別名:1.typedef     2.using SI = Sales_item;  //SI是Sales_item的別名聲明,把等號左側的名字規定成等號右側類型的別名 3.using可以起模板別名

3.auto:auto讓編譯器通過初始值來推算變量類型。auto i = 0, *p = &i; //ok     auto sz = 0, pi = 3.14; //error, 類型不統一

auto一般會忽略頂層const,保留底層const。如果希望保留頂層const,要明確指出 const auto p = ci;

設置類型為auto的引用時,初始值中的頂層const屬性保留。

底層 * 頂層: int const * const

4.decltype:類型指示符,頂層const能被保留,decltype((i)) d; //error, 對表達式套括號的結果永遠是引用,不套括號則僅當i是引用時,才是引用。

5.范圍for語句:for(declaration: expression) statement

expression是一個對象,表示一個序列;declaration部分定義一個變量,被用於訪問序列中的基礎元素,每次迭代該變量會被初始化為expression的下一個元素值。

如:

1 vector<int> v = {0, 1, 2, 3, 4, 5};
2 for(auto &r: v)
3     r *= 2;

6.標准庫begin()和end():begin(arr)返回指向arr首元素的指針, end(arr)返回指向arr尾元素下一位置的指針。

7.列表初始化返回值:vector<string> f(){ if(true) return {};  else return {"fun", "ok"}; }

8.定義尾置返回類型:任何函數的定義都能使用尾置返回類型,但對返回類型比較復雜的函數最有效,比如返回數組的指針或數組的引用。尾置返回類型跟在形參列表后,並以->開頭,本應該出現返回類型的地方則放置auto。比如:

auto func(int i) -> int(*) [10];//返回類型為int(*)[10]

9.容器的列表初始化:vector<const char*> articles = {"a", "an", "the"};

10.容器的emplace操作:emplace_frnont, emplace, emplace_back, 這些操作構造而不是拷貝元素,c.emplace(iter, "999-9999"); //向iter指向的位置插入以"999-9999"為構造參數的元素

11.lambda

[ capture ] ( params ) mutable exception attribute -> ret { body } (1)
[ capture ] ( params ) -> ret { body } (2)
[ capture ] ( params ) { body }

(3)

[ capture ] { body } (4)

mutable 修飾符說明 lambda 表達式體內的代碼可以修改被捕獲的變量,並且可以訪問被捕獲對象的 non-const 方法。

exception 說明 lambda 表達式是否拋出異常(noexcept),以及拋出何種異常,類似於void f(throw(X, Y)。

attribute 用來聲明屬性。

[]      // 不捕獲任何外部變量
[=]     // 以值的形式捕獲所有外部變量
[&]     // 以引用形式捕獲所有外部變量
[x, &y] // x 以傳值形式捕獲,y 以引用形式捕獲
[=, &z] // z 以引用形式捕獲,其余變量以傳值形式捕獲
[&, x]  // x 以值的形式捕獲,其余變量以引用形式捕獲
另有一點需注意。對於 [=] 或 [&] 的形式,lambda 表達式可直接使用 this 指針。但對於 [] 的形式,如果要使用 this 指針,必須顯式傳入:[this]() { this->someFunc(); }(); 

lambda后緊接();表示直接調用函數,括號內為參數。例:

http://wenku.baidu.com/view/77cd432e647d27284b73514b.html?from=search

    std::vector<int> c { 1,2,3,4,5,6,7 };
    int x = 5;
    c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; } ), c.end());
    for (auto i: c) {
        std::cout << i << ' ';
    }
    std::cout << endl;

    // the type of a closure cannot be named, but can be inferred with auto
    auto func1 = [](int i) { return i+4; };
    std::cout << "func1: " << func1(6) << '\n';

    // like all callable objects, closures can be captured in std::function
    // (this may incur unnecessary overhead)
    std::function<int(int)> func2 = [](int i) { return i+4; };
    std::cout << "func2: " << func2(6) << '\n';

    string result = [](const string & str) { return "Hello from " + str; }("second Lambda");
    cout << "Result: " << result << endl;
View Code

 

lambda的捕獲列表只用於局部非static變量,lambda可以直接使用局部static變量和它所在函數之外聲明的名字。值捕獲的變量的值是在lambda創建時拷貝而不是在調用時拷貝,引用捕獲則使用引用所綁定的對象,與正常引用類似,要保證lambda調用時變量是存在的。

每個lambda的類型都是唯一的,一般只能通過decltype和模板匹配來獲得其類型。

    vector<string> ve;
    int sz = 10;
    //接受一元謂詞的算法
    auto it = find_if(ve.begin(), ve.end(), [sz](const string &a){return a.size() >= sz; } );
    //接受二元謂詞的算法
    sort(ve.begin(), ve.end(), [](const string &a, const string &b){ return a.size() < b.size();} );

12.標准庫bind函數

參數綁定 http://blog.csdn.net/fjb2080/article/details/7527715

auto newCallable = bind(callable, arg_list);

arg_list中的參數可能包含形如_n的名字,其中n是整數,表示newCallable的參數,占據了傳遞給newCallable的參數的位置,_n表示為newCallable的第n個參數,在命名空間std::placeholeders里。

    using namespace std::placeholders;
    //例1:
    bool check_size(const string &s, string::size_type sz){
        return s.size() >= sz;
    }
    
    auto check6 = bind(check_size, _1, 6);
    string s = "hello";
    bool b1 = check6(s);//check6(s)會調用check_size(s, 6)
    //例2:f是一個包含5個參數的函數
    auto g = bind(f, a, b, _2, c, _1);
    g(X, Y);//即f(a, b, Y, c, X);
    
    //例3:ve是vector容器,cmp是一個比較函數
    sort(ve.begin(), ve.end(), cmp);
    sort(ve.begin(), ve.end(), bind(cmp, _2, _1));//按cmp逆序排列

 13.智能指針

shared_ptr允許多個指針指向同一個對象, unique_ptr則獨占所指向的對象。 

智能指針是一種類模板。

默認初始化的智能指針中保存着空指針,內部有一個關聯的計數器,計數器為0時釋放自己管理的對象。

shared_ptr<string> p4 = make_shared<string>(10, '9'); //類似順序容器的emplace函數,使用動態內存

附: shard_ptr與unique_ptr的簡單實現

 1 //  https://www.cnblogs.com/howo/p/8468713.html
 2 
 3 //
 4 //  SharedPtr.hpp
 5 //  SharedPtr
 6 //
 7 //  Created by 顧浩 on 24/2/18.
 8 //  Copyright © 2018 顧浩. All rights reserved.
 9 //
10 
11 #ifndef SHARED_PTR_H
12 #define SHARED_PTR_H
13 
14 #include <iostream>
15 
16 using namespace std;
17 
18 template<typename T>
19 class SharedPtr {
20 public:
21     SharedPtr() : _ptr((T *)0), _refCount(0)
22     {
23     }
24     
25     SharedPtr(T *obj) : _ptr(obj), _refCount(new int(1))
26     {
27         cout<<"create object : "<<*_ptr<<"\trefCount = 1"<<endl;
28     }
29     
30     SharedPtr(SharedPtr &other) : _ptr(other._ptr), _refCount(&(++*other._refCount))
31     {
32         cout<<"copy constructor : "<<*_ptr<<"\trefCount = "<<*_refCount<<endl;
33     }
34     
35     ~SharedPtr()
36     {
37         if(_ptr && --*_refCount == 0) {
38             cout<<*_ptr<<"\trefCount = 0. delete the _ptr:"<<*_ptr<<endl;
39             delete _ptr;
40             delete _refCount;
41         }
42     }
43     
44     SharedPtr &operator=(SharedPtr &other)
45     {
46         if(this==&other) return *this;
47         ++*other._refCount;
48         if(--*_refCount == 0) {
49             cout<<"in function operator = . delete "<<*_ptr<<endl;
50             delete _ptr;
51             delete _refCount;
52         }
53         _ptr = other._ptr;
54         _refCount = other._refCount;
55         cout<<"in function operator = . "<<*_ptr<<"\t_refCount = "<<*_refCount<<endl;
56         return *this;
57     }
58     
59     T *operator->()
60     {
61         if(_refCount == 0) return 0;
62         return _ptr;
63     }
64     
65     T &operator*()
66     {
67         if (_refCount == 0) return (T*)0;
68         return *_ptr;
69     }
70     
71 private:
72     T *_ptr;
73     int *_refCount;     //should be int*, rather than int
74 };
75 
76 #endif /* SharedPtr_h */
View Code
 1 #ifndef _UNIQUE_PTR_H
 2 #define __UNIQUE_H
 3 class Delete {   
 4 public:
 5     template<typename T>
 6     void operator()(T *p) const {
 7         delete p;
 8     }
 9 };
10 template<typename T,typename D = Delete >
11 class unique_ptr {
12 public:
13     explicit unique_ptr(T *pp = nullptr ,const D &dd = D() ): 
14         un_ptr(pp), del(dd)
15     {
16     }
17         
18     ~unique_ptr() 
19     { 
20         del(un_ptr); 
21     } 
22     
23     /* 不支持拷貝與賦值   */
24     unique_ptr(const unique_ptr&) = delete ;
25     unique_ptr& operator=(const unique_ptr& ) = delete ;
26 
27     /* 移動賦值與移動拷貝 */
28     unique_ptr( unique_ptr&& right_value):
29         un_ptr(right_value.un_ptr),del(std::move(right_value.del)) {
30         right_value.un_ptr = nullptr ;
31     }
32     
33     unique_ptr& operator=( unique_ptr&& right_value ) noexcept {
34         if(this != &right_value ){
35             std::cout << "operator && right_value " << std::endl ;
36             del(*this);
37             un_ptr = right_value.un_ptr;
38             del = std::move(right_value.del);
39             right_value.un_ptr =  nullptr ;
40         }
41         return *this ;
42     }
43     
44     //u.release()   u 放棄對指針的控制權,返回指針,並將 u 置為空
45     T* release(){ 
46         T *tmp = un_ptr ;
47         un_ptr = nullptr ;
48         return  tmp;
49     }
50     
51     /*
52     u.reset()   釋放u指向的對象
53     u.reset(q)  如果提供了內置指針q,就令u指向這個對象 
54     u.reset(nullptr) 將 u 置為空
55     */
56     void reset(T* q = nullptr){
57         del(un_ptr);
58         un_ptr = q; 
59     }
60     void swap(unique_ptr &other ) noexcept {
61         std::swap(un_ptr, other.un_ptr);
62         std::swap(del, other.del) ;
63     } 
64     T* get() { return un_ptr; }
65     D& get_deleter(){ return  del; }
66     T& operator*()  { return *un_ptr; }
67     T* operator->() { return  un_ptr; }
68 private:
69     T *un_ptr = nullptr ;
70     D del ;
71 };
72 #endif
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM