运行过程
一个C/C++程序运行经历的过程,预处理、编译、汇编、链接、执行。
其中编译阶段所有代码都是单独编译的,只是在最终的链接阶段所有的目标文件
①预处理(预编译):替换 #define,#ifdef,#ifndef,#else,#elif,#endif,#include(读取文件内容并插入)等#开头的命令
g++ -E main.cpp -o main.i
g++ -E student.cpp -o student.i
②编译,声明汇编代码文件。生成hello.s,它包含了一个汇编语言程序。汇编语言程序中的每条语句都以一种标准的文本格式确切的描述一条低级机器语言指令。
g++ -S main.i -o main.s
g++ -S student.i -o student.s
③汇编,将汇编代码文件转化为可执行的机器执行。
汇编器将汇编程序翻译为机器语言指令,把这些指令打包成可重定位目标程序(relocateble object program)的格式,并把结果保存在hello.o中。hello.o文件是二进制文件,因为他的字节编码是机器语言指令而不是ascii码。如果用文本编辑器打开hello.o会看到一堆乱码。
g++ -c main.s -o main.o
g++ -c student.s -o student.o
④链接,将所有的目标文件组织成一个可以执行的二进制文件。例如将将库函数文件(.o文件)合并到编译好的目标文件中,形成可执行文件。
g++ main.o student.o -o student
⑤运行:
最后执行该程序
./student
省略如上显式的过程,可以用一个命令执行生成可执行文件:
g++ main.cpp student.cpp -o student
参考:
https://blog.csdn.net/Zerore/article/details/121038305
智能指针
为智能指针就是⼀个类,当超出了类的作用域,类会自动调用析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时⾃动释放内存空间,不需要手动释放内存空间
- auto_ptr:允许剥夺所有权,存在潜在的内存崩溃问题
- unique_ptr(独占):避免资源泄露
- shared_ptr(共享、强引用):使用引用计数法,会有循环引用问题
- weak_ptr(弱引用):不控制生命构造和析构不会引起引用记数的增加或减少,协助shared_ptr循环引用问题
值传递、指针传递、引用传递
- 值传递:void f( int p),在栈中创建一份新的p变量,传入值
- 指针传递:void f( int *p),本质也是值传递(传入地址值)
- 引用传递:void f( int &p),对p的操作就是对实参的操作
内存分配
- 栈:由编译器管理分配和回收,存放局部变量和函数参数。
- 堆:由程序员管理,需要手动 new malloc delete free 进行分配和回收,空间较⼤,但可能会出现内存泄漏和空闲碎片的情况。
- 全局/静态存储区:分为初始化(Data段)和未初始化(Bss段)两个相邻区域,存储初始化和未初始化的全局变量和静态变量。Data段包含常量存储区(常量不允许修改)。
- 代码区(Text):存放程序的⼆进制代码,就是C程序编译后的机器指令,也就是我们常见的汇编代码,进程共享。
参考:
https://blog.csdn.net/MRCEHN/article/details/79615667
https://blog.csdn.net/JACKSONMHLK/article/details/114392343
static和const
static:全局变量和函数范围限制在文件内、函数变量类共享、局部变量不释放
const:常量只读、形参只读、函数对成员变量只读
C和C++的区别
- C++是C的超集,有更多的语法、关键字
- C++ 中在 malloc 和 free 的基础上增加了 new 和 delete
- C++ 中在指针的基础上增加了引⽤的概念
- C++ 允许⾃⼰定义⾃⼰的空间,
- C++是面向对象语言,有封装(class比struct更安全)、继承、多态(虚函数)特性。
- C++ 中增加了模板还᯿⽤代码,提供了更加强⼤的 STL 标准
C++和Java的区别
- Java是屏蔽了指针,C++可以直接控制指针
- C++可以多重继承,Java可以实现多接口
- Java完全面向对象,取消了 C++ 中的 struct 和 union
- Java所有对象都创建在堆上(new创建),有垃圾回收机制,C++没有
- Java 不支持操作符重载。操作符重载被认为是 C++ 的突出特性
- C++具有预编译(预处理)
- C++ 中有数据类型隐含转换的机制,Java 中需要限时强制类型转换
- C++中字符串是以 Null 终⽌符代表字符串的结束,⽽ Java 的字符串 是⽤类对象(string 和 stringBuffer)来实现的
- C++提供 goto 语句
C++常量
- 对于局部常量,存放在栈区;
- 对于全局常量,编译期⼀般不分配内存,放在符号表中以提高访问效率;
- 字面值常量,比如字符串,放在常量区。
_tmain 和 main函数
我们可以在头文件<tchar.h>里找到_tmain的宏定义
#define _tmain main
所以,经过预编译以后, _tmain就变成main了
_tmain 是高版本的微软 VC 编译器才有的,你查看一下 _tmain 的定义,会发现其实它和 main 是一样的。你把 _tmain 改为 main,不会有问题。相反,你如果在低版本的 VC 编译器,比如VC6.0中将 main 改为 _tmian ,就会出错。