pineisme / magicCppCode

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

####Those are the magic cpp codes collected by me

  • about ?:

    (i & 01 ? odd : even).push_back(thing);

    odd and even all continer

  • 关于initializer_list 包含在头文件<initializer_list>中,在使用时需要规定传入数据的类型如:

    myclass(std::initializer_list<int> list);

    此时,类的构造可以用花括号的 方法构造:

    myclass a={1,2,3,4};
  • A a;
    std::cout << typeid(a).name(); // 可以在编译时确定a的类型为A
    空对象占用一个字节,因为需要在内存中确定a的位置
    typeid(decltype(a_rb)).name(); // decltype产生的是编译时即可确定的声明类型,因此为A typeid(a_rb).name(); // 由于a_rb是多态类型的glvalue,typeid在运行时计算,因此为B

  • algorithm头文件
    找到最大值:

    auto p=std::max_element(arr.begin(),arr.end());
    return *p;
    auto p = std::::min_element(s.begin(),s.end());

    返回值p是迭代器,返回值需要加上*

    sort(s.begin(),s.end(),less<int>());
    sort(s.begin(),s.end(),greater<int>());

    注意end必须在你想呀排序的最后一个位置之后

  • 快排的基本格式

    while(front<rear){
        int mid = (front+rear)>>1;
        if(k[mid]<target){
            front= mid+1;
        }
        else rear=mid;
    }
    return front;

    需要注意的是

       void mysort(vector<int> &a, int l,int r)//自己写的快排 
    {
       int mid=a[(l+r)/2];//找中间的数进行2分 
       int i=l,j=r;
       while(i<j){
           while(a[i]<mid)
           i++;//找左半部分大于中间数的 
           while(a[j]>mid)
           j--;//找右半部分小于中间数的 
           if(i<=j)
           {
               swap(a[i],a[j]);//换位 
               i++;//左指针右移 
               j--;//右指针左移 
           }
       }
       if(l<j) mysort(a,l,j);
       if(i<r) mysort(a,i,r);
    }

- 容器的emplace插入  
    普通的push和insert操作都是传递元素类型对象本身,而emplace_front()和emplace_back()将参数传递给元素类型的构造函数,如:
    ```cpp
    //C用来保存myclass对象
    c.emplace_back("966",12);//传递给构造函数,且必须与构造函数相匹配
    c.push_back(myclass("966",12));
    ```
- list双向链表  
    list可以高效地在内部增加删除元素
    list有特殊的remove(p)操作,移除和参数匹配地元素
    remove_if(p),p可以是函数或则lambda表达式,也可是同类型的元素
    unique()可以移除连续重复的元素只保留一个,unique()可不接受参数,也可接收一个二元断言,true被认为是相等的。
    sort()也分为有参数和无参数。默认从小到大
- deque双端队列  
    deque只在首位插入较快
- vector  
    在为vector初始化时最好先定好大小,避免扩容时候重复拷贝。  
    使用vector初始化二维数组方法
    ```cpp
    vector<vector<int>> f(n + 1, vector<int>(26));
- lambda表达式
    ```cpp
    []() {}
    //[=]从外部捕获的变量=为值捕获,[&]表示按引用,[= ,&b]默认全部按值,b用引用,反之亦然
    //[]捕获值,()函数参数,{}函数体
    []() mutable ->T {}
    //T is returnn type, in some situation can be ommitted
    //If a lambda is marked mutable, it is allowed to mutata the values taht have been capture by value.
    auto mid = [&] { return v.begin() + v.size() / 2; };
    for (auto curr = v.begin(); curr != mid(); ++curr)
    //注意for循环中的mid必须加圆括号,可以理解为mid其实是一个函数
    ```
    [这里关于lambda讲得很好 from stackoverflow](https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11?r=SearchResults)

- static关键字  
    在类外的static关键字表明该函数和变量只能在该翻译单元(该文件内)内被找到,不能被其他文件使用,如果其他文件需要使用,则需要加extern关键字
    在类内使用static关键字:
    static此时的变量被所有的类试题共用,他不属于任何一实体。在类内声明在类外定义,在类内定义static变量 只有枚举和float可以使用const static flaot = 1;
        
    使用 static与全局变量的优势,静态成员没有进入全局命名空间,不会产生命名冲突,可以实现信息隐藏,静态成员变量可以试试private的

    静态成员函数为类服务而不是某一个具体的类,因为不属于某一个类,所以没有this指针,所以他无法调用不是静态成员的变量,静态成员函数之间可以相互访问。

- 继承   
    public 意为着,父类中的public和private的成员到子类中依然为public and private.
    protected means at the sub-class, the public and private members become protected.
    private means at the sub-class, the public and private members become private.

- 类相关
    嵌套类可以访问外围类的私有和保护的静态成员
- 虚函数  
    [这篇博客讲的好](https://blog.csdn.net/hackbuteer1/article/details/7558868)
    编译器会根据虚表意识到有共同的基类成员

- explict  
    禁止通过等于=符号对对象进行初始化,防止隐式类型转换

- static_cast,dynamic_cast,reinterpret_cast,const_cast  
    **static_cast**在编译期进行转换,无法安全监测  
    **dynamic_cast**在运行时对实际类型进行检测,如果是指针的话不能转换时返回nullptr值。  
    基类指针(引用)转换成派生类指针(引用)使用dynamic_cast更安全
    派生类和基类智能指针之间的转换可以用`std::dynamic_pointer_cast` and `std::static_pointer_cast`  
    `const_cast` can change const pointer or refrence to nonconst  
    when complier not allow you use `static_cast`, but you can ensure this behaviour is safe,you can use `static_cast`

- reverse()函数可以翻转容器  
    `reverse(s.begin(),s.end())`
- 指定小数输出精度  
    `cout<<setprecision(3)<<fixed<<a/b<<endl;`或者C代码`printf("%.指定的位数lf\n",要输出的数);`  
- functional  
    std:function为一个多态函数包装器
    在C语言中,使用函数指针可以让函数指针指向参数类型相同,返回值类型也相同的函数,通过函数指针实现多态  
    `typedef int (*func)();`  
    指向无参数输入,返回值为Int的函数.  
    `std::function<void()> func(&print1);`  
    `func=&print2`;  
    `std::function<int(int)> f=target`  
    store a lambda:  
    `function<void()> f = [](){do_something;};`  
    store bind result:  
    `std::function<void()> f_display_31337 = std::bind(print_num, 31337);`  
    
    当func被赋予了一个重载了()的对象时,可以向调用该函数一样使用该对象
    ```cpp
    class a{
        void operator()(){
            ...
        }
    }
    a A;
    func=A;
    func();<--can be used as a function
    ```
    实现function功能有两种方式,一种是通过类的多态即虚表来达到多态,一种是通过C语言的函数指针来实现。  
- bind()函数适配器  
    他接受一个函数,生成一个函数来改变原来函数的参数列表,比如减少原来函数的参数个数,或者顺序,以满足新的需求。
    ```cpp
    #include<functional>
    using namespace std::placeholders;<--占位符
    ```
    `bind(函数名,arg_list);`arg_list为用逗号分割的原来函数的参数列表,里面可能包含占位符`_n`代表新的函数里的参数位置。`_1` 代表这个参数在原函数中为第一个参数。
    ```cpp
    double devide(double x, double y){
        return x/y;
    }
    auto one_bind = std::bind(devide, 2, 10);<--- 0.5;
    auto two_bind = std::bind(devide, _1, 2);<--- two_bind(10)  = 5
    auto three_bind = std:bind(devide, _2, _1);<--- three(10,2) = 0.2
    auto four_bind = std:bind<int>(devide, _1, _2);<--- 指定返回类型为Int four_bind(10, 3) = 0.3
    ```
    `bind(..., bind(...), ...)`bind 可以嵌套  
- assert  
assert(表达式);如果表达式为假则打印错误信息并且退出
- thread  
    
- ifstream  
 用`ifstream input {name};`替换`FILE* input = fopen(name, "r");`
- 静态断言  
`static_assert` 用于在编译器检查,如果表达式为真,不作任何事情,如果为否,抛出编译错误就是提示字符串。常用与模板中
`static_assert(常量表达式,提示字符串);`  
- 枚举enum  
枚举力的值必须要在编译器可知
- 模板  
模板实参不能腿短返回类型,必须显示指定  
```cpp
template <typename T, typename U, typename RT>
RT max(T a, U b){
    return a>b?a:b;
}
cout<<::max<int,double, double>(1,3.1);
---默认情况下,返回参数由第一个模板参数确定
template <typename T,typename U>
T max(T a, U b){
    return a>b?a:b;
}
cout<<::max(1,3.1);
----
template <typename RT, typename T, typename U>
RT max(T a, U b) {
  return b < a ? a : b;
}

::max<double>(1, 3.14);  // OK:返回类型为 double,返回 3.14
//---C++14 can use atuto as return type
template <typename T, typename U>
auto max(T a, U b) {
  return b < a ? a : b;
}
//if you only support C++11 you need to add ->
template <typename T, typename U>
auto max(T a, U b) -> decltype(b < a ? a : b) {
  return b < a ? a : b;
}

使用std::common_type获取模板参数类型都能隐式转换到的类型,在C++14中你可以这么写

#include <type_traits>

template <typename T, typename U, typename RT = std::common_type_t<T, U>>
RT max(T a, U b) {
  return b < a ? a : b;
}

有时候你的模板参数必须是一个引用,但是你的返回值不能是一个引用,可以使用std::decay去掉引用修饰符等,退化到基本的类型。

#include <type_traits>

template<typename T, typename U, typename RT = std::decay_t<decltype(true ? T() : U())>>
RT max(T a, U b) {
  return b < a ? a : b;
}

在模板中使用constexpr:

constexpr auto fact(uint64_t n){
    if(n ==1 ){
        return n;
    }
    return n*fact(n-1);
}
constexpr auto i = ::fact(10);

可以在编译器获得i的值,需要注意constexpr在递归很多层时可能失败。
如果类模板有static数据成员,每种实例化类型都会实例化static数据成员。static成员函数和数据成员只被同类型共享。

About