C++笔记(一)
1.内链接和外链接:
gcc/g++编译的时候是以源文件cpp文件为单位,编译成一个个的.o文件(vsc++是obj),然后再把不同的.o文件链接起来。内链接的变量或函数在链接的时候不会拿与.o比较是否重复定义,也不会去寻找是否在其它文件中定义。如果是外链接则需要在不同的.o中比较是否有重定义,也会查看通过extern修饰的变量或函数声明在其他.o中的定义。因此我们可以得出内链接在编译时可以出现多次,而外链接的内容只可以出现一次。因此内链接的内容可以写在头文件但是外链接的内容最好写在cpp文件。
内部链接的内容:
任何变量和函数的声明,结构体的定义,类的定义,const常量定义,union的定义,enum定义,inline函数定义(包括自由内联函数和在类中的非自由内联函数,在C++中所有不在类中的函数称为自由函数),静态自由函数定义,静态友元函数定义,静态变量定义。
外部链接的内容:
除去内链接的内容外,其它变量函数的定义均是内链接。如非静态自由函数,类成员函数(不包括内联成员函数),非静态基本数据类型的定义如int,char等。需要注意的是类的静态成员函数和类的静态成员变量都是外链接。const修饰返回值的函数也是外链接。
根据上面内容可以看出为什么c++一般采用头文件声明cpp定义的方式。如果头文件定义那么当多个cpp包含时极可能发生报错。
2.extern作用:
extern表示可以外链接变量或者函数的定义在别的文件中,这样编译器遇到此变量和函数时会在其他模块中寻找定义,因此即便在此文件没有被定义也不会报错(除非在其它文件没找到定义)。extern只是声明,不是定义。因此只使用extern无法访问变量。extern修饰变量不消耗内存。使用如下:
//a.cpp
int x;
//b.cpp
extern x; //错误,没有说明类型无法进行后面的类型检查
extern int x;x+=1; //正确
extern int y; //错误,没有定义
此外extern也可用来进行链接指定,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的。
需要注意的是extern声明const而在其它cpp定义const常量会报错,因为const是内链接,编译器不会去寻找定义。但是如果定义时加入extern就会压制const的内链接属性,可以找到其它cpp定义的const常量,但是在头文件使用extern const定义会报错。看下面代码:
//a.h
const int a=0;//同时被b和c包含也没有问题,可以理解成b和c同时有一个属于自己的a常量,链接时不会检查
extern const b=0;//同时被b和c包含也有问题,b变量同时被b.cpp和c.cpp编译,链接时报错
extern const c;
//b.cpp
#include "a.h"
extern const b;
extern const c=0;
//c.cpp
#include "a.h"
extern const a; //错误,有声明无定义
extern const c; //正确,可以链接到b.cpp里的c
此外在头文件定义const常量会使每一个包含它的cpp在编译时生成一个常量,占用空间。因此最好使用头文件声明,源文件定义const的方式,这样程序只占用一份内存。
3.volatile关键字:
volatile修饰变量表示该变量可能因未知因素修改。正常编译器的做法应该是从变量的内存地址获得变量的值。但是编译器一般会对其进行优化。优化后如果在读取变量i的值时,如果该值与上次获取该值之间没有对其操作的代码,那么它会直接把上次读取的数据放入程序中,而不是从变量内存地址里面读。volatile修饰后则每次读取都重新从内存开始读。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具