• c++基础知识


    [1]namespace,即“命名空间”:

    一.用来组织和重用代码的,之所以有这样一个东西,是因为人类可用的单词太少,哦不同的人写的程序不可能所有的变量都没有重名现象,如果两个人写的文件中出现同名的变量或函数,使用起来就有问题了。为了解决这个问题,引入了这个概念,通过使用 namespace xxx;你所使用的库函数或变量就在该名字空间中定义,就不会引起冲突了。所谓命名空间,是一种将程序库名称封装起来的方法,它就像在各个程序库中立起一道道围墙。

    二.由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:

    1、直接指定标识符。例如,std::ostream而不是ostream,完整语句如下: std::cout << std::hex << 3.4 << std::endl;
    2、使用using关键字。 using std::cout; using std::endl; using std::cin; 以上程序可以写成 cout << std::hex << 3.4 << endl;
    3、最方便的就是使用using namespace std这样命名空间std内定义的所有标识符都有效;那么以上语句可以如下写: cout <<hex << 3.4 << endl.
    因为标准库很庞大,所以程序员在选择的类的名称或函数名时很有可能和标准库中的名字相同,为了避免名字冲突,就把标准库中的一切都被放在名字空间std中。
           无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。所以就有了<iostream.h>和<iostream>等等这样的头文件<iostream.h>是为了兼容以前的C++代码,<iostream>是为了支持新的标准。命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,不加".h"。
     

     [2]  c++ for_each

    相当于一个函数模板:

    template<typename InputIterator, typename Function>
    Function for_each(InputIterator beg, InputIterator end, Function f) {
      while(beg != end) 
        f(*beg++);
    }

    template< class InputIt, class UnaryFunction > UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f ); (1) template< class ExecutionPolicy, class ForwardIt, class UnaryFunction2 > void for_each( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, UnaryFunction2 f ); (2)

     Parameters

    first, last ---the range to apply the function to.

    policy---the execution policy to use. See execution policy for details.

              f---  function object, to be applied to the result of dereferencing every iterator in the range [first, last)

                             The signature of the function should be equivalent to the following:

                                  void fun(const Type &a);

                            The signature does not need to have const &.
                              The type Type must be such that an object of type InputIt can be dereferenced and then implicitly converted to Type.

     [3] Eigen: C++开源矩阵计算工具

    Eigen中关于矩阵类的模板函数中,共有6个模板参数,但是目前常用的只有前三个(分别表示矩阵元素的类型,行数和列数),如下所示:

     template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>  
     struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >  
    .......

      《视觉SLAM十四讲》e.g.:

        #include <iostream>  
        using namespace std;  
        #include <ctime>  
        // Eigen 部分  
        #include <Eigen/Core>  
        // 稠密矩阵的代数运算(逆,特征值等)  
        #include <Eigen/Dense>  
          
        #define MATRIX_SIZE 50  
          
        /**************************** 
        * 本程序演示了 Eigen 基本类型的使用 
        ****************************/  
          
        int main( int argc, char** argv )  
        {  
            // Eigen 中所有向量和矩阵都是Eigen::Matrix,它是一个模板类。它的前三个参数为:数据类型,行,列  
            // 声明一个2*3的float矩阵  
            Eigen::Matrix<float, 2, 3> matrix_23;  
          
            // 同时,Eigen 通过 typedef 提供了许多内置类型,不过底层仍是Eigen::Matrix  
            // 例如 Vector3d 实质上是 Eigen::Matrix<double, 3, 1>,即三维向量  
            Eigen::Vector3d v_3d;  
            // 这是一样的  
            Eigen::Matrix<float,3,1> vd_3d; 
          
            // Matrix3d 实质上是 Eigen::Matrix<double, 3, 3>  
            Eigen::Matrix3d matrix_33 = Eigen::Matrix3d::Zero(); //初始化为零  
            // 如果不确定矩阵大小,可以使用动态大小的矩阵  
            Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > matrix_dynamic;  
            // 更简单的  
            Eigen::MatrixXd matrix_x;  
            // 这种类型还有很多,我们不一一列举  
          
            // 下面是对Eigen阵的操作  
            // 输入数据(初始化)  
            matrix_23 << 1, 2, 3, 4, 5, 6;  
            // 输出  
            cout << matrix_23 << endl;  
          
            // 用()访问矩阵中的元素  
            for (int i=0; i<2; i++) {  
                for (int j=0; j<3; j++)  
                    cout<<matrix_23(i,j)<<"	";  
                cout<<endl;  
            }  
          
            // 矩阵和向量相乘(实际上仍是矩阵和矩阵)  
            v_3d << 3, 2, 1;  //向量
            vd_3d << 4,5,6;  //矩阵 
            // 但是在Eigen里你不能混合两种不同类型的矩阵,像这样是错的  
            // Eigen::Matrix<double, 2, 1> result_wrong_type = matrix_23 * v_3d;  
            // 应该显式转换  
            Eigen::Matrix<double, 2, 1> result = matrix_23.cast<double>() * v_3d;  
            cout << result << endl;  
          
            Eigen::Matrix<float, 2, 1> result2 = matrix_23 * vd_3d;  
            cout << result2 << endl;  
          
            // 同样你不能搞错矩阵的维度  
            // 试着取消下面的注释,看看Eigen会报什么错  
            // Eigen::Matrix<double, 2, 3> result_wrong_dimension = matrix_23.cast<double>() * v_3d;  
          
            // 一些矩阵运算  
            // 四则运算就不演示了,直接用+-*/即可。  
            matrix_33 = Eigen::Matrix3d::Random();      // 随机数矩阵  
            cout << matrix_33 << endl << endl;  
          
            cout << matrix_33.transpose() << endl;      // 转置  
            cout << matrix_33.sum() << endl;            // 各元素和  
            cout << matrix_33.trace() << endl;          //
            cout << 10*matrix_33 << endl;               // 数乘  
            cout << matrix_33.inverse() << endl;        //
            cout << matrix_33.determinant() << endl;    // 行列式  
          
            // 特征值,特征向量  
            Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigen_solver ( matrix_33 );  
            cout << "Eigen values = 
    " << eigen_solver.eigenvalues() << endl;  
            cout << "Eigen vectors = 
    " << eigen_solver.eigenvectors() << endl;  
          
            // 解方程  
            // 我们求解 matrix_NN * x = v_Nd 这个方程  
            // N的大小在前边的宏里定义,它由随机数生成  
            // 直接求逆自然是最直接的,但是求逆运算量大  
          
            Eigen::Matrix< double, MATRIX_SIZE, MATRIX_SIZE > matrix_NN;  
            matrix_NN = Eigen::MatrixXd::Random( MATRIX_SIZE, MATRIX_SIZE );  
            Eigen::Matrix< double, MATRIX_SIZE,  1> v_Nd;  
            v_Nd = Eigen::MatrixXd::Random( MATRIX_SIZE,1 );  
          
            clock_t time_stt = clock(); // 计时  
            // 直接求逆  
            Eigen::Matrix<double,MATRIX_SIZE,1> x = matrix_NN.inverse()*v_Nd;  
            cout <<"time use in normal invers is " << 1000* (clock() - time_stt)/(double)CLOCKS_PER_SEC << "ms"<< endl;  
              
            // 通常用矩阵分解来求,例如QR分解,速度会快很多  
            time_stt = clock();  
            x = matrix_NN.colPivHouseholderQr().solve(v_Nd);  
            cout <<"time use in Qr compsition is " <<1000*  (clock() - time_stt)/(double)CLOCKS_PER_SEC <<"ms" << endl;  
          
            return 0;  
        }  

      [5]push_back用法

    c++中的vector头文件里面有这个push_back函数,在vector类中作用为在vector尾部加入一个数据。
    string中也有这个函数,作用是字符串之后插入一个字符。

     如果是指标准模板库(stl)中容器的一般pushback()操作函数,那么是指在容器尾端插入一项数据,比如
    vector<int> a(10);
    a.pushback(10);
    那么a的尾端,同时也是唯一一个数据a[0]就会为设置为10。

    函数原型
    void push_back(value_type_Ch);
    参数 _Ch
    -->The character to beadded to the end of the string. 在vector类中: voidpush_back(const_Ty&_X) { insert(end(),_X); }
    在vector
    <_Bool, _Bool_allocator>类中: voidpush_back(constbool_X) { insert(end(),_X); }

       [5]C++ [stl_vector.h]之iterator

    Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
    由于Iterator模式的以上特性:与聚合对象耦合,在一定程度上限制了它的广泛运用,一般仅用于底层聚合支持类,如STL的list、vector、stack等容器类及ostream_iterator等扩展iterator。

     https://www.cnblogs.com/yc_sunniwell/archive/2010/06/25/1764934.html

       [6]std::nth_element

    C++ 
    Algorithm library
    Defined in header <algorithm>
            
    template< class RandomIt >
    void nth_element( RandomIt first, RandomIt nth, RandomIt last );     (1)     
    template
    < class ExecutionPolicy, class RandomIt > void nth_element( ExecutionPolicy&& policy, RandomIt first, RandomIt nth, RandomIt last ); (2) (since C++17)
    template
    < class RandomIt, class Compare > void nth_element( RandomIt first, RandomIt nth, RandomIt last, Compare comp ); (3)
    template
    < class ExecutionPolicy, class RandomIt, class Compare > void nth_element( ExecutionPolicy&& policy, RandomIt first, RandomIt nth, RandomIt last, Compare comp ); (4) (since C++17)

     nth_element(first, nth, last, compare)

    求[first, last]这个区间中第n大小的元素,如果参数加入了compare函数,就按compare函数的方式比较。

    nth_element仅排序第n个元素(从0开始索引),即将位置n(从0开始)的元素放在第n大的位置,处理完之后,默认排在它前面的元素都不比它大,排在它后面的元素都不比它小。

    例如:array[first, last)元素区间,排序后,array[nth]就是第n大的元素(从0开始).

    但[first, nth) 和 [nth,last)区间的大小顺序不一定。但是可以确定的是array[nth]一定是整个区间里第n大的元素。

    [first,nth)中的元素都是不大于array[nth]的,[nth, last)中的元素都是不小于array[nth]的。

        [7]->

    ->是C语言和C++语言的一个运算符,叫做指向结构体成员运算符,用处是使用一个指向结构体或对象的指针访问其内成员。 

    一个指针当用来指向一个结构体对象时,称之为结构体指针或对象指针。结构体指针或对象指针中的值是所指向的结构体或对象的首地址。通过结构体指针或对象指针即可访问该结构体或对象。这需要用到结构体关键字struct和C++类关键字class

         [8]C++ 位运算 & | << >> ^ ~ %

    http://blog.csdn.net/fox64194167/article/details/20692645

    (1) << 向左移位移

    <<简单例子(向左移一位,右边自动补0)

    11 << 1 = 22

      00001011 << 1

      00010110 = 22

    相当于二进制的每个数都变成当前值的两倍,结果就是变成当前值的两倍。

    n * 2 == (n << 1)

    推广下就是(注意可能会溢出)

    (2) >> 向右位移

    >>简单例子(向右移一位,左边自动补1)

    11 >> 1 =  5

    00001011 >> 1

    00000101 = 5

    注意到最后一位的1被干掉了。

    比较实用的例子是:

    int n = n / 2     等价于   int n = n >> 1  等价于 int n >>= 1

      [9]C++ 函数 .reset()

    auto &lines = wm[word];
                if (!lines)
                    lines.reset(new set <line_no>);
    
    lines的类型是shared_ptr<set<line_no>> 
    如果lines指针位空  reset重置新的一个shared_ptr对象

       [10]<math.h>是C标准函数库中的头文件,在C++中一般用<cmath>。此头文件中声明了一系列函数来计算常见的数学运算和变换:

    
    	std::abs: 处理int类型的取绝对值
    	     fabs: 处理double类型的取绝对值
    fabsf(): 处理float类型的取绝对值 std::fma(x,y,z):x*y+z; std::sin: 正弦; std::asin: 反正弦; std::sinh: 双曲正弦; std::asinh: 双曲反正弦; std::cos: 余弦; std::acos: 反正弦; std::cosh: 双曲余弦; std::acosh: 双曲反余弦; std::tan:正切; std::atan:反正切; std::atan2: 反正切; std::tanh: 双曲正切; std::atanh: 双曲反正切; std::sqrt: 计算平方根; std::cbrt: 计算立方根; std::hypot: 计算两个数平方的和的平方根; std::pow:幂运算; std::ceil: 不小于给定值的最近整数; std::floor/ floorf/ floorl: 不大于给定值的最近整数; std::fmod: 两数除法操作的余数(rounded towards zero); std::trunc: 不大于给定值的最近整数; std::round: 舍入取整; std::lround: 舍入取整, 返回long int; std::llround: 舍入取整, 返回long long int; std::nearbyint: 使用当前的舍入模式取整(fegetround()); std::remainder: 两数除法操作的余数(rounded to nearest); std::remquo: 两数除法操作的余数; std::rint: 使用当前的舍入模式取整(fegetround()); std::lrint: 使用当前的舍入模式取整(fegetround()),返回long int; std::llrint: 使用当前的舍入模式取整(fegetround()),返回long longint; std::exp: ex; std::frexp: 将一个浮点数分解为有效数(significand)及以2为底的幂(x = significand* 2exp); std::ldexp: x *2exp; std::exp2: 2x; std::expm1: ex-1; std::scalbn: x *FLT_RADIXn; std::scalbln: x* FLT_RADIXn; std::log: ln(x); std::log10: log10(x); std::modf: 将一个浮点数分解为整数及小数部分; std::ilogb: 返回以FLT_RADIX为底,|x|的对数值,返回值为整数; std::log1p: ln(1+x); std::log2: log2(x); std::logb: 返回以FLT_RADIX为底,|x|的对数值,返回值为浮点数; std::erf: 误差函数; std::erfc: 互补(complementary)误差函数; std::tgamma: 伽玛函数; std::lgamma: log-伽玛函数; std::copysign(x,y):返回x的值及y的正负符号组成的浮点数; std::nan: Generatequiet NaN; std::nextafter(x,y): 返回x之后y方向上的下一个可表示值; std::nexttoward(x,y): 返回x之后y方向上的下一个可表示值; std::fdim(x,y): Thefunction returns x-y if x>y, and zero otherwise; std::fmax: 返回较大的值; std::fmin: 返回较小的值; std::fpclassify:为浮点值归类,返回一个类型为int的值; std::isfinite: 检测是否是有限值; std::isinf: 检测是否是无穷大值; std::isnan: 检测是否是非数型; std::isnormal: 检测是否是normal值,neitherinfinity, NaN, zero or subnormal; std::signbit: 检测是否是负数; std::isgreater: 检测第一个数是否大于第二个数; std::isgreaterequal:检测第一个数是否大于或等于第二个数; std::isless: 检测第一个数是否小于第二个数; std::islessequal:检测第一个数是否小于或等于第二个数; std::islessgreater:检测第一个数是否不等于第二个数; std::isunordered:检测两个浮点数是否是无序的.

     [10]C++中的Cast

    http://blog.csdn.net/stan1989/article/details/12588279 

    • Dynamic_Cast

      (1)首先dynamic_cast能够应用于指针转换

      子类指针转换成父类指针,成功;

      父类指针转换成子类指针,就分为两种情况:

            <a>父类指针p如果真的指向子类对象,那么转换时成功的;

            <b>反之,失败,dynamic_cast返回NULL。

      (2)其次dynamic_cast能够应用于引用之间的转换(与指针类似)。

      子类引用转换成父类引用,成功;

      父类引用转换成子类引用,就分为两种情况:

             <a>父类引用ob,如果真的指向子类对象,那么转换时成功的;

            <b>反之,失败,dynamic_cast,会抛出bad_cast异常

      (3)其他将null指针,转换成任何类型的指针;将任何类型的指针转换成void*类型的指针。

    • Static_Cast

      Static_cast可以转换相关联的类,可以从子类转换成父类。也能从父类转向子类,但是如果转换的父类指针(或者父类引用)所指向的对象是完整的,那么是没有问题;但是如果所指向的对象并不完整,那么会出现runtime错误。

      Static_cast相对于dynamic_cast而言,除了能转换指针和引用,还能应用于任何能够隐式转换的情况

    • Reinterpret_Cast

      reinterpret_cast和上面讲到的两个cast,适用范围更加广泛,它可以适用于任何类型指针之间的转换

      该操作不会去进行动态类型或者静态类型的检测,它仅仅将值强行赋值过去。从某种意义上对编译器进行了一种欺骗,同时也带来了一定的不安全性。所以在使用这个cast的时候,要慎重。下面是这个操作的适用情况:

      (1)   Int和指针之间的相互转换;

      (2)   无关联类指针之间的转换;

      (3)   函数指针之间的转换

    • Const_Cast

      const_cast如它的名字,它是去除修饰在对象上的constvolatile

       隐式转换,在代码中很难寻找;但是使用C++的这种cast可以轻松的找出,代码中哪里使用强制转换等。

     [11].insert   https://docs.scipy.org/doc/numpy/reference/generated/numpy.insert.html

    numpy.insert(arr, obj, values, axis=None)[source] 在给定索引之前沿给定轴插入值
    Parameters:    
               arr : array_like
                        Input array. 
               obj : int, slice or sequence of ints
                        Object that defines the index or indices before which values is inserted.它定义在插入值之前的索引或索引支持多个插入时,obj是一个标量或一元序列(类似于调用多次插入)。
               values : array_like
                        Values to insert into arr. 
               axis : int, optional
                      Axis along which to insert values. 插入值的轴

     [12]vector中resize()和reserve()区别

    1、***resize(n) 

    调整容器的长度大小,使其能容纳n个元素。如果n小于容器的当前的size,则删除多出来的元素。否则,添加采用值初始化的元素。

     ***resize(n,t)

    将所有新添加的元素初始化为t。

    2、reserve(n)

    预分配n个元素的存储空间。

    了解这两个函数的区别,首先要搞清楚容器的capacity(容量)与size(长度)的区别。

    size指容器当前拥有的元素个数;而capacity则指容器在必须分配新存储空间之前可以存储的元素总数,也可以说是预分配存储空间的大小。

    resize()函数和容器的size息息相关。调用resize(n)后,容器的size即为n。至于是否影响capacity,取决于调整后的容器的size是否大于capacity。

    reserve()函数和容器的capacity息息相关。调用reserve(n)后,若容器的capacity<n,则重新分配内存空间,从而使得capacity等于n。

    如果capacity>=n呢?capacity无变化。

    从两个函数的用途可以发现,容器调用resize()函数后,所有的空间都已经初始化了,所以可以直接访问。

    reserve()函数预分配出的空间没有被初始化,所以不可访问。

  • 相关阅读:
    「JSOI2015」套娃
    「JSOI2015」非诚勿扰
    「JSOI2015」送礼物
    「JSOI2015」子集选取
    「JSOI2015」salesman
    「JSOI2015」字符串树
    [2]树的DFS序
    hdu 6058 Kanade's sum
    UVALive 6907 Body Building
    CF617/E XOR and Favorite Number
  • 原文地址:https://www.cnblogs.com/Jessica-jie/p/7811757.html
Copyright © 2020-2023  润新知