C/C++知识点、疑问

一、知识点

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() 用法

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;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值