参考链接
基础知识
源文件从文本到可执行文件经历的过程
-
预处理,根据文件中的预处理指令来修改源文件的内容。如#include指令,作用是把头文件的内容添加到.cpp文件中,产生.ii文件,
-
编译,将其翻译成等价的中间代码或汇编代码,产生汇编文件(.s文件)
-
汇编,把汇编语言翻译成目标机器指令,产生目标文件(.o或.obj文件)
-
链接,例如,某个源文件中的函数可能引用了另一个源文件中定义的某个函数;在程序中可能调用了某个库文件中的函数,产生可执行文件(.out或.exe文件)
C++11的新特性
- 自动类型推导auto、范围for循环、lambda表达式、智能指针、多线程等
gcc不同优化等级的区别
- -O0:不作任何优化
- -O1:对程序做部分编译优化,对于大函数,优化编译占用稍微多的时间和相当大的内存。使用本项优化,编译器会尝试减小生成代码的尺寸,以及缩短执行时间,但并不执行需要占用大量编译时间的优化。 它主要对代码的分支,常量以及表达式等进行优化。
- -O2:编译器会试图提高代码性能而不会增大体积和大量占用的编译时间。会尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间。
- -O3:使用伪寄存器网络,普通函数的内联,以及针对循环的更多优化。
- -Os:主要是对代码大小的优化
C++的内存管理
-
该内容存疑
-
一个程序被加载到内存中,这块内存首先就存在两种属性:静态分配内存和动态分配内存。
- 静态分配内存:是在程序编译和链接时就确定好的内存。
- 动态分配内存:是在程序加载、调入、执行的时候分配/回收的内存。
-
代码段: 代码段(code segment/text segment)通常是指用来存放 程序执行代码 的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.【存储的是二进制后的程序代码】
-
数据段 :数据段(data segment,也叫GVAR global value)通常是指用来存放程序中 已初始化 的 全局变量 的一块内存区域。数据段属于静态内存分配。 【存储全局已初始化的变量】
-
BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。【存储全局未初始化的变量】
-
堆(heap) :堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)【存储初始化的局部变量】
-
栈(stack) :栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中 存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放**【存储动态未初始化变量】**
问题
堆和栈的区别
-
堆是由低地址向高地址扩展;栈是由高地址向低地址扩展
-
堆中的内存需要手动申请和手动释放;栈中内存是由OS自动申请和自动释放,存放着参数、局部变量等内存
-
堆中频繁调用malloc和free,会产生内存碎片,降低程序效率;而栈由于其先进后出的特性,不会产生内存碎片
-
堆的分配效率较低,而栈的分配效率较高
A* a = new A; a->i = 10;在内核中的内存分配上发生了什么
-
A *a:a是一个局部变量,类型为指针,故而操作系统在程序栈区开辟4/8字节的空间(0x000m),分配给指针a。
-
new A:通过new动态的在堆区申请类A大小的空间(0x000n)。
-
a = new A:将指针a的内存区域填入栈中类A申请到的地址的地址。即*(0x000m)=0x000n。
-
a->i:先找到指针a的地址0x000m,通过a的值0x000n和i在类a中偏移offset,得到a->i的地址0x000n + offset,进行*(0x000n + offset) = 10的赋值操作,即内存0x000n + offset的值是10。
全局变量、static变量初始时间
- 对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。
- C++标准定为全局或静态对象是有首次用到时才会进行构造,并通过atexit()来管理。在程序结束,按照构造顺序反方向进行逐个析构。
- 全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。
文件重定义
// Person.h
class Person
{
...
}
// Worker.h
#include"Person.h"
class Worker : public Person
{
...
}
// Farmer.h
#include"Person.h"
class Farmer : public Person
{
...
}
-
在Farmer.h和Worker.h中都包含了Person.h,导致Person这个类被重定义了。
-
使用宏定义解决:
// Person.h
#ifndif PERSON_H
#define PERSON_H
class Person
{
...
}
#endif
条件编译
作用
- 根据预先定义的参数选择性的编译代码,以使代码适用于不同的运行环境等。比如环境中未安装ROS(机器人操作系统),则可以不对ROS部分的代码进行编译,不至于编译不通过。
使用
- CMakeLists.txt中
option(USE_ROS "use ros" ON)
IF(USE_ROS)
message(STATUS "Build with ros")
add_defination(-D_ROS_)
ENDIF(USE_ROS)
IF(USE_ROS)
# 通过判断USE_ROS是否启用来选择性编译下面指令
find_package(catking ...)
ENDIF(USE_ROS)
- C/C++代码中
#ifdef _ROS_ // 与CMakeLists.txt中USE_ROS或_ROS_名称一致
#include<ros/ros.h>
#endif