C++ 学习笔记

面向对象编程三大特性------封装、继承、多态
一.封装:就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只一些对外接口使之与外部发生联系。对于封装而言,一个对象它所封装的是自己的属性和方法。
优点:1、良好的封装能够减少耦合。2、类内部的结构可以自由修改。3、可以对成员进行更精确的控制。4、隐藏信息,实现细节。
二.继承:是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。
三.多态:简单概括为“一个接口,多种方法”,即用的是同一个接口,但是效果各不相同。就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。多态:同一名称不同的功能实现方式,目的是达到行为标识统一,减少程序中标识符的个数,实现方式:重载函数和虚函数

函数声明中包含形参(parameter),调用函数时必须提供实参(argument).
使用句点运算符访问成员Humun Tom;Tom.IntroduceSelf(),
使用指针运算符访问成员(如果对象使用new在自由存储区中实例化,或者有指向对象的指针,则可使用指针运算符来访问,如Humum* pTom=new Human(); pTom->IntroduceSelf();)。如果有一个指向对象的指针,则使用指针运算符最合适;如果栈中实例化了一个对象,并将其存储到一个局部变量中,则使用句点最合适。
类实例和类对象基本一回事,实例化类时,将获得一个实例,也称为对象。
类的私有属性,只能在对象构造函数内部使用;类公有属性在对象实例化后调用。

类的成员函数:成员函数的原型要写在类体中,说明了函数的参数表和返回值类型,与普通函数不同的是,实现成员函数时要指明类的名称。形式为 返回值类型 类名::函数成员名(参数表){函数体}  其中的函数一般为短小内联函数。还有一种:类A里声明成员函数void f()时,没有在类的声明里给出f的定义,那么在类外定义f时,就要写成void A::f(),表示这个f()函数是类A的成员函数。
类的六个默认成员函数:构造函数,拷贝构造函数,析构函数,赋值操作符重载,取地址操作符重载,const修饰的取地址操作重载。

构造函数定义:主要用来在创建对象时初始化对象,构造函数的命名必须和类名完全相同,没有返回值,只调用一次。形式为:类名::类名{函数体}
        类名::类名(参数){函数体}
        类名::类名(参数):初始化列表{函数体}  //所有类非静态数据成员初始化

拷贝构造函数:只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰)。它是特殊的构造函数,创建对象时使 用已存在的同类对象来进行初始化,由编译器自动调用。

析构函数:与构造函数的功能相反,析构函数是在对象被销毁时,由编译器自动调用,完成类的一些资源清理和汕尾工作。没有显式给出,编译器会默认生成一个。

C++ 类的继承与派生:类的继承,是新的类从已有类那里得到已有的特性。或从已有类产生新类的过程就是类的派生。原有的类称为基类或父类,产生的新类称为派生类或子类。
声明方式: class 派生类A:public/private 基类B,public/private 基类n {派生类成员声明;};
一个派生类可以同时有多个基类,这种情况称为多重继承。

类 unique_lock 是通用互斥包装器,允许延迟锁定、锁定的有时限尝试、递归锁定、所有权转移和与条件变量一同使用。unique_lock中的unique表示独占所有权。unique_lock独占的是mutex对象,就是对mutex锁的独占。因此加锁时新建一个对象lock,unique_lock<mutex> lock(mMutex);这个对象生命周期结束后自动解锁。进入这个线程时mMutex锁住,当mMutex锁没有释放时只能等待。std::mutex:该类表示普通的互斥锁, 不能递归使用。

C++的数据类型:c++中的数据类型分为两大类:预定义类型和自定义数据类型。预定义类型包含:整型int、字符型char、布尔型bool、浮点型float、空类型,指针类型;自定义数据类型包含:数组、结构体struct、联合体union、枚举enum

字节(byte)是计算机信息技术中用于计量存储容量的一种计量单位,作为一个单位来处理的一个二进制数字串,是构成信息的一个小单位。最常用的字节是八位bit的字节,即它包含八位的二进制数。
结构体struct:结构体是由一系列具有相同类型或者不同类型的数据构成的数据集合。
struct 名称{ 
数据类型 变量名1;
数据类型 变量名2;
数据类型 变量名n;
}结构体变量名;
联合体union:联合体的使用方式和结构体及普通变量类似。联合体的主要作用就是节省内存,因为联合体中的·变量不像结构体中的成员变量那样,系统会给其中的每一个变量都分配相应的内存。在联合体中,所有的成员变量共享一块内存空间。该内存空间是其成员变量中占字节数最多的变量所占用的内存空间,并且所有的成员变量共用这一块内存空间,因此联合体中所有成员变量地址是一样的。
union 名称{
类型变量符 变量名;
......
类型变量符 变量名;
};
枚举类型enum:枚举类型是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。enum 枚举名{
标识符[=整型常数],
...
标识符[=整型常数]
} 枚举变量;

头文件作用:头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明(declaration),而定义文件用于保存程序的实现 (implementation)。具体地说,头文件中可以包括:用户构造的数据类型(如枚举类型),外部变量,外部函数、常量和内联函数等具有一定通用性或常用的量。而一般性的变量和函数定义不宜放在头文件中。例如:#include<stdio.h>中的头文件stdio.h作用是让链接器通过头文件里的函数声明找到函数实际代码所在的位置即所在的库文件,这样才能使用该函数的实际代码,函数的实际代码的实现过程是先让链接器通过头文件里函数的申明找到函数实际代码所在的位置即所在的库文件,再通过#include语句把链接器所找到的函数实际代码用链接器把函数的实际代码链接到当前文件即所要执行的程序中。

bind绑定成员函数:类的成员函数不同于普通的函数,因为成员函数指针不能直接调用operator(),它必须被绑定到一个对象或指针,然后才能得到this指针进而调用成员函数。因此bind需要 “牺牲”一个占位符,要求提供一个类的实例、引用或者指针,通过对象作为第一个参数来调用成员函数,即:bind(&X::func,x,_1,_2,…); 对于bind(fuction,this)返回的是一个绑定this后的function;

智能指针(Smart Pointer):智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈上的变量自动被销毁,智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使用时需添加头文件<memory>。shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象。接受指针参数的智能指针构造函数是explicit的,因此,我们不能将一个内置指针隐式的转换为一个智能指针,必须使用直接初始化形式:  shared_ptr<int> p2(new int(1024)); shared_ptr<int> p1 = new int(1024); // 错误,必须使用直接初始化形式    

*标准模板库STL以模板类std::list方式向提供一个双向链列表,主要优点是插入和删除元素速度快,且时间固定。基本操作,实例化、插入和删除无素、对无素进行反转和排序。

this是指向实例化对象本身时候的一个指针,里面存储的是对象本身的地址,通过该地址可以访问内部的成员函数和成员变量。
boost::timer库用于性能测试等需要计时的任务,timer.elapsed()
argv[0]来获取可执行程序的路径。
template<class T>函数模板  模板(Templates)使得我们可以生成通用的函数,这些函数能够接受任意数据类型的参数,可返回任意类型的值,而不需要对所有可能的数据类型进行函数重载。这在一定程度上实现了宏(macro)的作用。出现<>的地方就是模板的类型入口。template<typename T> 这个是定义模板的固定格式,因为T是一个模版实例化时才知道的类型,所以编译器更对T不知所云,为了通知编译器T是一个合法的类型,使用typename语句可以避免编译器报错。 template < typename var_name > class class_name; 表示var_name是一个类型, 在模版实例化时可以替换任意类型,不仅包括内置类型(int等),也包括自定义类型class。 换句话说,在template<typename Y>和template<class Y>中, typename和class的意义完全一样。

struct 把一些有共同特征的变量封装在内部,通过一定方法访问修改内部变量。

vector是C++标准库中的容器类,std::vector<>是模板类, 用于管理任意类型的对象的动态数组,在解构时释放所管理的动态内存。std::vector<> 在头文件 <vector> 中定义。vec.begin返回一个当前vector中起始元素的迭代器,vec.end返回一个当前vector容器中末尾元素的迭代器,vec.push_back在容器的尾端插入一个数据,作为序列访问 vector 中的元素:序列(sequence)在 STL 中是一个非常重要的概念,所有的容器类型和算法都涉及到,而且所有的算法都是建立在“序列”这个概念之上的。“序列”是一个线性结构,由一个指示其起始和一个指示结束的叠代子(iterator)来决定。设计中经常需要遍历vector容器,常用的三种vector遍历方式,
1,下标索引遍历:for(int i = 0; i < v.size(); ++i)
2,迭代器遍历(iterator智能指针一种): for(vector<int>::iterator it = v.begin();it != v.end(); ++it)
3,copy函数遍历:泛型算法中copy,  copy(v.begin(), v.end(), ostream_iterator<int> (cout, " "))
vector.size()指容器当前拥有的元素个数, resize是改变容器的大小, reserve是容器预留空间。

ROS中点云数据结构sensor_msgs::PointCloud,sensor_msgs::PointCloud2,pcl::PointCloud<T>
其中sensor_msgs::PointCloud2和pcl::PointCloud<T>之间的转换使用pcl::fromROSMsg和pcl::toROSMsg,而sensor_msgs::PointCloud,sensor_msgs::PointCloud2之间的转换使用sensor_msgs::convertPointCloud2 ToPointCloud ,sensor_msgs::convertPointCloudToPointCloud2. 其中rviz中显示的点云的数据格式都是sensor_msgs::PointCloud2, pcl::PCLPointCloud2 这是PCL点云库中定义的一种的数据格式,在RVIZ中不可显示。

enum枚举类型:特殊的变量只有特定的几种可能取值可以定义为枚举类型。枚举是指将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。枚举是常数,因此枚举元素又称为枚举常量。
每个C++/C程序通常由头文件(header files)和定义文件(definition files)组成。头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明(declaration);定义文件用于保存程序的实现 (implementation)。定义文件就是src文件。

pcl中octree及其查找相关函数
octree:若不为空树的话,树中任一节点的子节点恰好只会有八个,或零个。八叉树作为三维空间中点的重要数据结构在PCL中有很多应用:空间划分、近邻搜索、点云压缩和空间变化检测。空间划分:八叉树是将空间平均得分为8个部分,每个节点就是一个部分。划分到最后,一个叶子结点代表一个最小的空间范围,称之为体素。八叉树的建立过程也就是空间划分的过程。 基于八叉树的近邻搜索可以分为三种:范围搜索\ k最近邻搜索\体素内搜索。
k最近邻搜索(K Nearest Neighbor Search):K近邻算法的核心思想,无法判定当前待分类点是从属于已知分类中的哪一类时,依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。K 近邻算法使用的模型实际上对应于对特征空间的划分。K 值的选择,距离度量和分类决策规则是该算法的三个基本要素:K 值的选择会对算法的结果产生重大影响,算法中的分类决策规则往往是多数表决,距离度量一般采用 Lp 距离: Lp空间是由p次可积函数组成的空间。
半径内近邻搜索"(Neighbors within Radius Search):以圆心点作为近邻搜索的目标点,以圆的半径作为判断的依据:是否有范围内的点不在结果中。
体素内搜索是octree特有的Neighbors within VOxel Search:在给定查询点后,将其所在体素内的所有其他点作为搜索目标的搜索方式。
步骤:1.初始化octree树:float resolu=1.0f;//确定分辨率即最小体素边长,
pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree (resolution);
octree.setInputCloud (cloud);octree.addPointsFromInputCloud ();//载入点云:
载入点云后,八叉树会根据分辨率和点云的空间维度得到深度,并得到一个Bounding Box,即一个长方体盒子,它能将整个点云装在它的内部,也就相当于划分出来了点云的空间范围。如果点云的空间范围我们是知道的,那么可以通过defineBoundingBox函数可以直接设定octree.defineBoundingBox(0, 0, 0, 1, 1, 1);//分别为min_x,min_y, min_z, max_x, max_y,max_z
2.输入查询点进行搜索:bool octree.voxelSearch(searchPoint, pointIdxVec);
searchPoint是输入的查询点,pointIdxVec输出的搜索到相同体素内的点集,返回true表明这个体素存在,否则不存在

目前pcl::octree模块中类有16个,class pcl::octree::OctreePointCloudSearch<PointT/LeafT/OctreeT>, 类OctreePointCloudSearch实现了基于八叉树的点云近邻高效搜索。它的关键成员函数如:bool Search(const PointT& point, std::vector<int>& pointldx_data):给定查询点point,通过point确定其所在的体素,返回体素中所有点的索引存储在pointldx_data
bool voxelSearch(const int index, std::vector<int>&pointldx_data):功能同上,区别是查询点通过index指定
int nearestKSearch(const PointCloud& cloud, int dex, int k, std::vector<int>& k_indices, std::vector<float>& k_sqr_distances): 近邻搜索,cloud为搜索的点云对象,index为查询点的索引,k为搜索返回的近邻个数,k_indices为返回近邻索引向量,k_sqr_distances存储近邻点对应的距离平方向量。
int nearestKSearch(const PointT& p_q, int k, std::vector<int>& k_indices, std::vector<float>& k_sqr_distances) 功能同上,p_q为指定查询点,其他参数同
void approxNearestSearch(const PointCloud& cloud, int query_index, int& result_index, float& sqr_distance)近似近邻搜索,参数同上
int radiusSearch(const PointCloud& cloud, int dex,double radius,std::vector<int>& k_indices, std::vector<float>& k_sqr_distances,unsigned int max_nn=0)  获取查询点radius半径内的近邻点集,cloud为搜索的点云对象,index为查询点的索引,k为搜索返回的近邻点个数,k_indices为返回近邻索引向量,k_sqr_distances存储近邻点对应的距离平方向量,max_nn默认为0,如果设置就返回半径内领域个数上限,返回值为返回领域点的个数。
int getIntersectedVoxelCenters(Eigen::Vector3f origin, Eigen::Vector3f direction, AlignedPointT Vector& voxelCenterList) const 给定过点origin指向direction的直线,返回直线相交的点云对应八叉树的体素中心点组成的向量,并存储在voxelCenterListkh ,返回值为相交体素个数
int getIntersectedVoxelIndices(Eigen::Vector3f origin, Eigen::Vector3f direction, std::vector <int>& k_indices) const 功能同上,k_indices存储相交体素的索引
int boxSearch(const Eigen::Vector3f& min_pt, const Eigen::Vector3f& max_pt, std::vector <int>& k_indices)const 搜索处于指定立方体内的点集,min_pt\max_pt指定立方体的左前下角坐标及右后上方坐标来定义立方体,k_indices存储落在立方体内的点索引
void setInputCloud(const PointCloudConstPtr& cloud_arg, const IndicesConstPtr& indices_arg= IndicesConstPtr()) 指定构建八叉树的点云
void setEpsilon(double eps) 设置搜索时的精度
void setResolution(double resolution_arg)设置八叉树的体素分辨率
void addPointsFromInputCloud() 显示调用将点云添加到八叉树管理结构中
void addPointsFromCloud(const int pointldx_arg, IndicesPtr indices_arg)添加到对应索引中的点到八叉树中,其中pointldx_arg为索引,indices_arg索引序列的指针
void addPointToCloud(const PointT& point_arg, PointCloudPtr cloud_arg, IndicesPtr indices_arg)添加点point_arg到点云cloud_arg的indices_arg索引下,同时添加到八叉树中
bool  isVoexlOccupiedAtPoint(const PointT& point_arg) const判断点point_arg所处的空间是否存在于八叉树体素中
bool  isVoexlOccupiedAtPoint(const double pointX_arg,const double pointY_arg,const double pointZ_arg) const 同上,其中是点坐标
int getOccupiedVoxelCenter(AlignedPointTVector&voxelCenterList_arg) const返回所有被点云占据的体素中心存储在voxelCenterList_argkh ,返回值为被占据的体素个数
int getApproxIntersectedVoxelCentersBySegment(const Eigen::Vector3f& origin, const Eigen:: Vector3f& end, AlignedPointTVector&voxel_center_list, float precition=.2)用参数origin和end给定空间一线须,该函数求得与该线段体素中心,存储在voxel_center_list,并返回相交体素的个数
void deleteVoxelAtPoint(const PointT& point_arg)删除指定点所在的八叉树中管理的体素或叶子节点
void defineBoundingBox(const double minX/Y/X//maxX/YZ)指定八叉树的包围盒
void getBoundingBox(const double minX/Y/X//maxX/YZ)获取八叉树的包围盒上下限

GICP:GenerativeIterativeClosestPoint,这种方法基于使用各向异性函数在最近的点匹配后来优化匹配。

KD树与八叉树搜索效率比较
KD树的效率明显高于八叉树,由于随着数据量的增加,八叉树的深度也迅速增加,从而导致其检索速度变慢;KD树在数据量适中或较小的情形下具有极快的搜索速度,但随着数据量增加,同样会增加其检索的复杂度,导致速度很快下降:充分利用了两者的优势:先利用八叉树实现概略检索,再利用KD树实现检索精确定位,这样有效平衡了各环节的数据处理工作量,提高了整体效率。

OpenCV中相关函数笔记
cvRound (double value):对一个double型的数进行四舍五入,并返回一个整型数
KeyPoint类主要是存储图像中检测到的关键点(特征点),特征点主要是由特征检测器在图像中进行检测得到的,常见的特征检测器有:Harris corner detector, cv::FAST, cv::StarDetector, cv::SURF, cv::SIFT, cv::LDetector等。关键点主要是由二维特征,尺度(与需要考虑的邻域直径成正比),方向和一些其他的参数。关键点邻域是由生成描述子(通常被表示成一个特征向量)的算法分析得到的。在不同图像中表示相同对象的关键点能通过cv::KDTree或其他方法匹配到。
cvCvtColor是Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像,参数CV_RGB2GRAY是RGB到gray
像素坐标[u,v]:以图像左上角为原点建立以像素为单位的直接坐标系u-v。像素的横坐标u与纵坐标v分别是在其图像数组中所在的列数与所在行数。
cv::Mat 在当前的OpenCV开发中,Mat是最最常见的数据单元。构造函数:cv::Mat::Mat()默认构造函数,生成一个矩阵并由OpenCV提供的函数(create() 和 imread() )来分配储存空间。Mat类可以分为两个部分:矩阵头和指向像素数据的矩阵指针。矩阵头包括数字图像的矩阵尺寸、存储方法、存储地址和引用次数等,矩阵头的大小是一个常数,不会随着图像的大小而改变,但是保存图像像素数据的矩阵则会随着图像的大小而改变,通常数据量会很大,比矩阵头大几个数量级。这样,在图像复制和传递过程中,主要的开销是由存放图像像素的矩阵而引起的。
常用构造函数:cv::Mat::Mat(int rows,int cols,int type), cv::Mat::Mat(Size size,int type), cv::Mat::Mat(int ndims,const int * sizes,int type,const Scalar& s), Scalar参数作用是能够通过Scalar数据类来初始化元素值,cv::Mat::Mat(const Mat & m)。
cv::Mat常用成员函数: at()访问矩阵元素返回对指定数组元素的引用,channels()返回图像的通道数,clone()矩阵复制,create()分配矩阵新的存储单元,setTo将矩阵中所有的或部分元素设置为指定值,empty()如果数组没有元素则返回true,。
矩阵的结构主要由宽度(width)、高度(height)、类型(type)、行数据长度(step)和一个指向数据的指针构成。
 一个图像的通道数是N,就表明每个像素点处有N个数,一个m×n的N通道图像,其图像矩阵实际上是n行N×m列的数字矩阵。OpenCV中图像的通道可以是1、2、3和4。
cv::line绘制连接两个点的线段,void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 ); img 图像, pt1 线段的第一个端点, pt2 线段的第二个端点, color线段的颜色, thickness 线段的粗细程度,line_type 线段的类型,8 (or 0) - 8-connected line(8邻接)连接线,CV_AA - antialiased线条,shift 坐标点的小数点位数。

printf,sprintf,cout的区别
printf:是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息,调用格式为: printf("<格式化字符串>", <参量表>)
sprintf:是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。
cout:C++编程语言互换流中的标准输出流,需要iostream支持,与前两者相比更安全智能,扩展性强,流风格简洁。
*std::to_string(int val)整形转字符串,std::stoi(str ) ?? atoi   头文件 <string>

pcd文件中的格式为x y z rgb而不是分开的r g b,所以在原数据的基础上要进行变形,
由r g b得到rgb(float):int rgb = ((int)r << 16 | (int)g << 8 | (int)b);  式中的“<<”为左移符号;(rgb的加码)
由rgb得到r,g,b(int): int r = (rgb >> 16) & 0x0000ff;  int g = (rgb >> 8) & 0x0000ff;  int b = (rgb) & 0x0000ff; (rgb的解码)
其中0x0000ff是十六进制,等价于255

C++在new时的初始化的规律可能为:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0。   new int;// 分配内存,  未初始化 new int();// 分配内存,初始化为0    new int(2);// 分配内存,初始化为2

stdafx.h中没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行。在64位中改成stdio.h或者去掉。

html,xml,yaml文件区别
html文件(HyperText Mark-up Language)是一种制作万维网页面的标准语言,是万维网浏览器使用的一种语言,它消除了不同计算机之间信息交流的障碍。它是目前网络上应用最为广泛的语言,也是构成网页文档的主要语言。HTML文件是由HTML命令组成的描述性文本,HTML命令可以说明文字、图形、动画、声音、表格、链接等。HTML文件的结构包括头部(Head)、主体(Body)两大部分,其中头部描述浏览器所需的信息,而主体则包含所要说明的具体内容。
xml:即可扩展标记语言,xml是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。元素格式:<title>XML编程</title>
YAML是一个类似 XML JSON 的标记性语言。YAML 强调以数据为中心,并不是以标识语言为重点。因而 YAML 本身的定义比较简单,号称“一种人性化的数据格式语言”.
date: 2015-02-01
items:
  - no: 1234        
- descript: cpu

<<,~,=,&,^符号的意义
<<是按位bit左移运算,~是按位取反运算,=是赋值运算,&是按位与(只有对应的二个二进位都为1时,结果位就为1),^二进制的异或运算(如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0)。 1<<n,表示左移n位,乘以2^n, >>右移n位,除以2^n.其余位补0.以上计算都是二制运算,先把数字转换成二制,再进行按位运算。

循环结构中break、continue、return和exit的区别:
break语句的使用场合主要是switch语句和循环结构。在循环结构中使用break语句,如果执行了break语句,那么就退出循环,接着执行循环结构下面的第一条语句。如果在多重嵌套循环中使用break语句,当执行break语句的时候,退出的是它所在的循环结构,对外层循环没有任何影响。如果循环结构里有switch语句,并且在switch语句中使用了break语句,当执行switch语句中的break语句时,仅退出switch语句,不会退出外面的循环结构。
continue语句是这5种结束循环的方式中最特殊的,因为它并没有真的退出循环,而是只结束本次循环体的执行。
如果在程序中遇到return语句,那么代码就退出该函数的执行,返回到函数的调用处,如果是main()函数,那么结束整个程序的运行。
exit()函数与return语句的最大区别在于,调用exit()函数将会结束当前进程,同时删除子进程所占用的内存空间,把返回信息传给父进程。当exit()中的参数为0时,表示正常退出,其他返回值表示非正常退出,执行exit()函数意味着进程结束;而return仅表示调用堆栈的返回,其作用是返回函数值,并且退出当前执行的函数体,返回到函数的调用处,在main()函数中, return n和exit(n)是等价的。

size_t,int,ssize_t, char, unsighned char的区别
size_t的真实类型与操作系统有关,在32位架构中被普遍定义为:typedef   unsigned int size_t;
在64位架构中被定义为:typedef  unsigned long size_t;size_t在32位是4字节,在64位是8字节
int在不同架构下都是4字节,与size_t不同;且int为带符号数,size_t为无符号数
ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与long int
内存中char与unsigned char都是一个字节,唯一的区别是,char的最高位为符号位,因此char能表示-128~127, unsigned char没有符号位,因此能表示0~255.在表示byte时,都用unsigned char,

保留三位小数点的表示:double b; double x=(int)(b*1000+0.5)/1000.0;(+0.5表示四舍五入)

Eigen 库中位姿的表达形式:
旋转矩阵(3*3):Eigen::Matrix3d
旋转向量(3*1):Eigen::AngleAxisd
四元数(4*1):Eigen::Quaterniond
平移向量(3*1):Eigen::Vector3d
变换矩阵(4*4):Eigen::Isometry3d

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值