一、知识点
1.1 函数返回值类型为bool
当函数返回值为bool时,函数体内的实现语句中可以没有return true或return false语句;调用函数时也可以没有相应的bool类型变量接收。
#include <iostream>
using namespace std;
bool test01()
{
cout << "hello ubuntu" << endl;
return true;
}
int main()
{
test01();
//system("pause");
return 0;
}
1.2 有返回值的函数被调用时,也可以没有变量接收
#include <iostream>
using namespace std;
int func()
{
cout<<"hello";
return 3;
}
int main()
{
func(); //func()函数返回值类型为int,但并没有变量接收
return 0;
}
2. break与return false的区别:
break: 使得跳出当前循环,还会继续运行下面代码
return false: 直接终止整个程序的运行,不会在继续运行下面代码
while (UnsyncedData.size() >= 2) {
if (UnsyncedData.front().time > sync_time)
return false;
if (UnsyncedData.at(1).time < sync_time) {
UnsyncedData.pop_front();
continue;
}
if (sync_time - UnsyncedData.front().time > 0.2) {
UnsyncedData.pop_front();
return false;
}
if (UnsyncedData.at(1).time - sync_time > 0.2) {
UnsyncedData.pop_front();
return false;
}
break;
}
代码原理连接
此代码为两个传感器的数据的时间戳同步时进行数据插值的代码,核心思想是让容器第一个数据时间比插入时刻早,第二个数据时间比插入时刻晚:
1)如果第一个数据时间比雷达时间还要靠后,即插入时刻的前面没有数据,那么就无从插入,直接退出
2)如果第一个数据比插入时刻早,第二个数据也比插入时刻早,那么第一个时刻的数据是没意义的,应该接着往下找,并删除第一个数据
3)如果雷达采集时刻已经处在前两个数据的中间了,但是第一个数据时刻与雷达采集时刻时间差过大,那么中间肯定丢数据了,退出
4)同样,如果第二个数据时刻与雷达采集时刻时间差过大,那么也是丢数据了,也退出
以上四个限制条件如果都通过了,那么就算是找到对应位置了。
3.argc与argv
当执行a.exe1123asdgf34时,每个参数将被转换为main字符串并存储在argv中。此时,argc=5 argv={‘a.exe ‘,’ 1 ‘,’ 123 ‘,’ asdgf ‘,’ 34’} argc:整数用于* argv[ ]:指针数组用于存储指向您的字符串参数的指针,并且每个元素指向一个参数。
4.std::find()
5 const static 区别
6 map.emplace()
函数用于通过在容器中插入新元素来扩展map容器,仅当键不存在时才进行插入。
返回值类型是pair,pair中第一个值指向新插入元素的迭代器,第二个代表是否插入成功。
emplace函数讲解
7 uint16的最大值
// num_values = 65536 uint16的最大值+1
size_t num_values = std::numeric_limits<uint16>::max() + 1;
8 {}声明作用域
在C/C++中大括号指明了变量的作用域,
在大括号内声明的局部变量其作用域自变量声明开始,到大括号之后终结。
// 变量a的作用域为for循环
int main()
{
for(int a=0;a<9;a++)
{}
return 0;
}
// 变量a的作用域为main函数
int main()
{
int a;
for( a=0;a<9;a++)
{}
return 0;
}
9 {}初始化变量
#include <iostream>
#include <vector>
using namespace std;
void func(vector<int> v)
{
for(int i = 0; i < v.size(); i++)
{
cout << v[i] << endl;
}
}
int main()
{
func({6,7}); // 使用{6,7}初始化了一个vector,并作为fun函数的实参 // 等价于注释代码
//vector<int> v{6,7};
//func(v);
return 0;
}
10.范围for语句遍历类的vector类型的成员变量
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
public:
A (vector<int> v):v_(v){}
using ConstIterator = std::vector<int>::const_iterator;
ConstIterator begin() const
{
return v_.begin();
}
ConstIterator end() const
{
return v_.end();
}
private:
vector<int> v_;
};
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
A a(v);
for (int i:a) cout << i << endl;
return 0;
}
主要就是在类的public下定义begin()和end()函数接口,关于范围for循环的详解参考C++primer P168
那么是否可以直接使用for (int i:a.v_) 遍历类对象的vector成员变量吗?
理论上是可以的,但是需要将成员变量定义在public下,不然在外部无法访问。这样的话,从封装的角度来看是不好的,因为可以在外部随意改变成员变量的值。从封装的角度出发,一般将成员变量定义在private下,将允许对成员变量进行的操作(即函数接口)定义在public下。这样外部就只能按照定义好的接口对成员变量进行操作。
11 函数指针
// 当函数指针指向的是普通函数时
int function(int a, int b)
{
cout << "call Fun" << endl;
return a + b;
}
int main(void)
{
int (*FP)(int, int); // 函 数 指 针 的 声 明 方 式
FP = function; // 第 一 种 赋 值 方 法
// FP = &function; // 第 二 种 赋 值 方 法
FP(1,2); // 第 一 种 调 用 方 法
// (*FP)(1,2); // 第 二 种 调 用 方 法
return 0;
}
// 当函数指针指向的是类的成员函数时
class MyClass
{
public:
int Fun(int a, int b)
{
cout << "call Fun" << endl;
return a + b;
}
};
int main()
{
MyClass* obj = new MyClass;
int (MyClass::*pFun)(int, int) = &MyClass::Fun;
// 成 员 函 数 指 针 的 声 明与初始化
(obj->*pFun)(1, 2); // 通 过 对 象 来 调 用 成 员 函 数 指 针
delete obj;
return 0;
}
12 指针初始化
PoseWithCovarianceStampedPtr odom_lo = std::make_shared<PoseWithCovarianceStamped>();
std::shared_ptr<CloudSubscriber> cloud_sub_ptr = std::make_shared<CloudSubscriber>(nh, "/kitti/velo/pointcloud", 100000);
13 常量指针和指针常量
常量指针:指向常量的指针
指向的值不可改,指向可改。
const int a = 1;
const int b = 2;
const int* p = &a;
p = &b; // 正确,指向可改
//*p = 5; // 错误,指向的值不可改
int a = 1;
int b = 2;
const int* p = &a;
cout << "p = " << *p << endl; // p = 1
//p = &b; // 正确,指向可改
//*p = 5; // 错误,指向的值不可改
a = 5; // 正确,可以通过修改a的值改变指针指向的值
cout << "p = " << *p << endl; // p = 5
指针常量:指向不可改,指向的值可改
const int a = 1;
const int b = 2;
int *const p = &a;
//p = &b; // 错误,指向不可改
*p = 5; // 正确,指向的值可改
指针常量也可指向常量对象,此时指针的指向和指向的值都不可改。
const int a = 10;
const int *const p = &a;
14 vector.erase() 用法
15 lambda 表达式
#include <iostream>
using namespace std;
class AddNum
{
public:
AddNum(int num):num_(num){}
int addNum(int x) const{
return num_ + x;
}
int operator()(int y){
return num_ + y;
}
private:
int num_;
};
int main()
{
AddNum an(10);
// 调用成员函数实现两个数相加
int n = an.addNum(5);
cout << "n : " << n << endl;
// 调用仿函数(函数对象)实现两个数相加
int m = an(6);
cout << "m : " << m << endl;
}
对于功能简单的类,可以使用 lambda 表达式代替,这样代码看起来更简洁。
#include <iostream>
#include <functional> // function 类型需要添加的头文件
using namespace std;
int main()
{
// lambda 表达式声明,相当于实现了一个类
function<int(int)> lambda = [num = 10](int c){
return num + c;
};
// 这样也是可以的
// auto lambda = [num = 10](int c){
// return num + c;
// };
// 调用 lambda 表达式实现两个数相加
int p = lambda(7);
cout << "p : " << p << endl; // 输出<p : 17>
}
lambda 总结:[]内的值可以理解为类的成员变量,不需要给定数据类型,系统会自动推断,需要初始化。返回值类型也会自动推断。
二、疑问
1.内存四区
局部变量a和b都在栈区,大小都为4个字节,为何相距12个字节?
void test01()
{
int a = 1;
int b = 2;
cout << (int)&a << endl;
cout << (int)&b << endl;
cout << sizeof(a) << endl;
cout << sizeof(b) << endl;
}