- 静态链接库、动态链接库(共享库)、目标文件、可执行文件
C++源程序经过编译生成中间目标文件,经过链接,将中间目标文件缺少的启动代码和库代码链接进来。
静态链接库:静态链接是将中间目标文件调用的函数/过程链接到可执行文件中,成为文件的一部分。如果多个目标文件调用同一静态库中的相同部分,每个目标文件都要进行链接。
动态链接库(共享库):动态链接所调用的函数/过程并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息。当程序运行时,才与动态库建立实际的链接关系。
*参考:https://blog.csdn.net/biggbang/article/details/44653705
- new分配内存
typeName * pointer_name=new typeName;//new运算符根据数据类型确定分配的空间大小,返回地址
int * pn=new int;//pn为指针,*pn为值
.
.
delete pn;//释放new分配的内存
int * pi=new int[10];//使用new分配数组,在程序运行阶段需要才会创建,还可以更改数组大小,成为动态联编;编译时分配数组内存,为静态联编。
.
.
delete [] pi;//new与delete配对使用,new []与delete[]配对使用
delete只能用来释放new分配的内存,除此之外,delete空指针是被允许的。
- 智能指针
C++11中使用的智能指针包括:unique_ptr;shared_ptr;weak_ptr。实际上智能指针是栈上的模板类对象,实现了类似指针的功能。因为智能指针是对象,如果要获取实际的裸指针,需要使用get()方法。
shared_ptr:必须使用new分配的内存:shared_ptr<string> pss (new string);
unique_ptr:必须使用new或new [ ]分配的内存:unique_ptr<double> pda (new double);unique_ptr<double [ ]> pda(new double(5))。
*参考:https://blog.csdn.net/k346k346/article/details/81478223
- 指针常量与常量指针
指针(是)常量:int*const p,本质上是一个常量,指针说明指向数据的类型;指针本身是一个常量,指向的地址不能改变,其内容可以修改。
常量(的)指针:const int* p / int const *p(两者等价),本质上是一个指针,指向的内容为常量,不可改变,但指针的地址可以改变。
- 串口发float数据
//串口只能以当个字节形式发送
float yaw;
uint8_t data[4];
p=(unsigned char*)&yaw;
data[0]=(unsigned char)(*(p+0));
data[1]=(unsigned char)(*(p+1));
data[2]=(unsigned char)(*(p+2));
data[3]=(unsigned char)(*(p+3));
- 数组作为函数参数
不管函数形参何种形式,传递的均是数组的指针,相当于按地址传递。有以下几种形式的写法:
void fun1(int* param);
void fun1(int param[4]);
void fun1(int param[]);
- 复制(拷贝)构造函数
调用时机:当用一个对象初始化一个新的对象时(**重载赋值运算符是两个 已经存在/初始化过的对象 赋值时调用)
具体调用的场景:函数按值传递对象;函数返回对象;编译器生成临时对象(**重点就是初始化一个新的对象,就调用)
默认复制拷贝构造函数(浅复制):逐个复制非静态数据成员,按值进行复制。
浅复制的这两个特点就注定有两个隐患,以《C++ Primer》的例子来说:
class StringBad //默认复制构造
{
private:
int* arr=new int[4];//浅拷贝传递的为指针,同下
char* str;//字符串指针,当进行复制构造时 sailor.str=sport.str,此时,复制的是指针的值,得到两个指向同一个
字符串的指针,当析构一个对象,内存被释放一次,当另外一个对象再次析构时,内存将被释放两次,可能导致程序异常终止。
int len;//按值默认复制构造正常。
static int num_strings;//静态类成员无论创建了多少的对象,程序都只创建一个静态类成员的副本,所有对象共享同一个静态成员。
所以在进行默认复制构造时,如果静态变量的值在创建新对象时需要改变,则需要使用深复制来显式的手动实现。
.
.
}
StringBad sport;
将默认复制构造函数改为深复制如下:
String::StringBad(const StringBad& st)
{
int* arr=new int[4];
std::strcpy(arr,st.arr);
num_strings++;//手动修改静态值
len=st.len;
str=new char[len+1];//手动new
std::strcpy(str,st.str);//实现按值复制
}
- 递归与迭代
- 空指针与野指针
空指针:没有存储任何内存地址,地址被赋值0。int* p=nullptr(C++引入)/NULL(传统C写法)
野指针:没有初始化的指针,指向未知地址。long* p; *p=223323
- i++与++i
用于返回值:i++返回原值;++i返回加1后的值。
不用返回值:二者用法相同,执行效率略微不同。
++i相当于 i=i+1; return i; 左值
i++相当于 temp=i;i=i+1;return temp;右值
- 多线程 join( )
调用join( )方法的线程对象在执行结束后才能返回,否则处于阻塞状态。
https://www.cnblogs.com/adorkable/p/12722209.html
- volatile关键字
volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。
https://www.runoob.com/w3cnote/c-volatile-keyword.html
- std::mutex
多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁)。
https://www.jianshu.com/p/8378e74733d6
- 向量索引 "( )" 与 “[ ]”
Eigen库对两种运算符都做了重载,效果相同,如下:
operator()(Index index)
{
eigen_assert(index >= 0 && index < size());
return coeffRef(index);
}
operator[](Index index)
{
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
eigen_assert(index >= 0 && index < size());
return coeffRef(index);
}
但是std库只重载了 “[ ]",如下:
operator[](size_type __n) _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_subscript(__n);
return *(this->_M_impl._M_start + __n);
}
- 判断两个浮点数是否相等
浮点数的比较需要考虑浮点数的精度问题,if(fabs(a-b)<=eps_0),eps_0为相等的精度。