zoukankan      html  css  js  c++  java
  • 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) << '
    ';
    
        // 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) << '
    ';
    
        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<<"	refCount = 1"<<endl;
    28     }
    29     
    30     SharedPtr(SharedPtr &other) : _ptr(other._ptr), _refCount(&(++*other._refCount))
    31     {
    32         cout<<"copy constructor : "<<*_ptr<<"	refCount = "<<*_refCount<<endl;
    33     }
    34     
    35     ~SharedPtr()
    36     {
    37         if(_ptr && --*_refCount == 0) {
    38             cout<<*_ptr<<"	refCount = 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<<"	_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
  • 相关阅读:
    前端的貌似不顺道整个 小程序,不是那么回事哈
    sql server 大批数据插入时,时间过长的问题
    web api 权限控制
    推荐一个测试Web API, web service工具
    ConcurrentDictionary的用法
    Socket
    微信小程序(一)
    List常用几种方式
    c# 文件下载
    自定义身份验证
  • 原文地址:https://www.cnblogs.com/dirge/p/6204067.html
Copyright © 2011-2022 走看看