各类新鲜小问题

各类新鲜小问题

  • 压栈顺序从右到左
  • 在main之前执行函数
  • 内存申请与释放(底层实现)
  • 模板类template
  • 构造函数不能声明为虚函数
  • 多态时要虚析构
  • 队列(Queue)与消息队列(Message Queue)
  • 互斥锁和二进制信号量
  • 重定位

本文章专门用于记录学习过程中遇到的感觉很新鲜的问题,以及一些冷知识

压栈顺序从右到左

刚听还觉得这有啥区别,实际上是表示这一行代码往栈里面放的顺序,不是栈开口朝左朝右,那当然没区别了
比如:

	int p = 0;
	printf("%d %d %d \n",p++,++p,p++);

结果是2 2 0,因为先放最右边的p++,放了个0,然后放++p,放了个2,然后放p++,放了个2,最后从栈弹出来,2 2 0
C语言从右向左保存临时数据的原因是:
为了支持可变长参数,以printf函数为例,,定义是这样的:

printf(const char* format,…)

右边的参数数量不定,如果讲fomat置于栈底,我们不知道偏移多少个单位才能到首个参数
最左边的参数存放的是参数个数,我们必须将其置于栈顶,才方便我们知道有几个

在main之前执行函数

可以通过constructor/destructor来指定函数执行顺序在main之前/之后,例如:

void before() __attribute__ ((constructor))
void after() __attribute__ ((destructor))

void before(){
	printf("before");
}
void after(){
	printf("after");
}
int main(){
	printf("main");
	return 0;
}

输出的结果就会是 before main after

内存申请与释放(底层实现)

new运算分两个阶段: (1 )调用:operator new配置内存;(2)调用对象构造函数构造对象内容

delete运算分两个阶段: (1)调用对象析构函数; (2)调用::operator delete释放内存

为了精密分工,STL allocator将两个阶段操作区分开来:内存配置有alloc:allocate()负责, 内存释放由alloc:deallocate()负责;对象构造由::construct()负责, 对象析构由::destroy()负责。

同时为了提升内存管理的效率,减少申请小内存造成的内存碎片问题,SGI STL采用了两级配置器,当分配的空间大小超过128B时,会使用第一级空间配置器; 当分配的空间大小小于128B时,将使用第二级空间配置器。第一级空间配置器直接使用malloc()、realloc()、 free()函数进行内存空间的分配和释放,而第二级空间配置器采用了内存池技术,通过空闲链表来管理内存。

模板类template

使用示例:构建一个通用的栈stack

template <typename T>
class Stack {
public:
  Stack() : top(-1) {}
  void push(T val) {
    data[++top] = val;
  }
  T pop() {
    return data[top--];
  }
private:
  T data[100];
  int top;
};

由于使用了模板template ,使得stack在应用的时候,可以随意指定内部元素类型,如stackstack等等

构造函数不能声明为虚函数

因为虚函数表是在构造过程中创建的,你还没构造呢,哪来的虚函数表,也就没有所谓的虚构造函数,无法确定对象具体的对象。

多态时要虚析构

多态就是定义个父类指针,然后让他指向子类实现,比如:

class * Animal = class dog;

如果子类里面在堆区开内存了,delete只能调用到父类的析构函数,子类这块内存就没释放掉,内存泄漏了

多态还可以是子类覆盖父类同名函数,比如

class Animal{
	virtual shit(){};
}
class Dog : public Animal{
	virtual shit(){Dog shit};
}

这里面,当子类调用该函数时,就会调用到子类的该函数,子类这个函数也得写成虚函数,这和虚函数的实现方式有关:子类的虚函数指针指向子类的虚函数表中该虚函数所在位置,父类的虚函数指针指向父类的虚函数表中该虚函数所在位置,所以二者会调用到不同的实现,形成多态。

队列(Queue)与消息队列(Message Queue)

队列是FreeRTOS中的概念,其严格遵循队列的性质,只能从队首读,只能从队尾写,也可以按消息上传者的id来读
而消息队列是Linux中的概念,相对不那么严格,允许随机读取,也可以按类型读。

互斥锁和二进制信号量

本来以为二者完全相同,实际上还是略有不同的。
互斥锁可以

重定位

(1)Nand Flash:单位容量价格低、CPU不能直接访问、容易坏块;
(2)Nor Flash:单位容量价格高、CPU能直接访问、不易坏块、但是不能像内存一样写;
总结:代码必须保存在Flash、硬盘等掉电不丢失的存储介质中,但是代码又不能再这些ROM存储介质中直接运行,必须在RAM中运行,所以设备启动时必须要先将代码重定位到RAM中。

你可能感兴趣的:(c++)