尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

C/C++ 杂记-1

C/C++ 杂记-1 编译Table 1 预处理行为序号步骤名称工作内容1头文件展开将所有#include引入的头文件递归嵌入到源文件中2宏文本替换代码中所有宏标识符替换为定义的文本内容3去除注释删除代码里全部单行//、多行/* */注释4条件编译展开解析#ifdef/else/endif剔除不生效的代码分支Table 1 PreprocessingSerial NumberStep NameWork Details1Header file expansionRecursively expand all included header files into the source file2Macro text replacementReplace all macro names with corresponding literal text3Comment eliminationDelete all single-line and multi-line comments in code4Conditional compilation expansionParse#ifdef/#else/#endifand discard unreachable code branchesTable 2 编译链接核心工作操作项详细说明数据段合并合并所有目标文件的全局变量、静态变量、常量字符串到统一段区地址回填重定位解析未定义符号为代码引用填充正确内存地址库引入加载静态库/动态库完成跨文件外部符号解析Table 2 Compile Link Core WorkOperation ItemSpecific DescriptionData segment mergingMerge global variables, static variables, string constants from all object files into unified segmentsAddress backfilling (relocation)Resolve undefined symbol addresses and fill correct memory addresses for referencesLibrary introductionLoad static/dynamic libraries, resolve external cross-file symbols局部数组0初始化局部数组 char str[20]; 存储随机垃圾值不会自动全部置零char str[20] {};//置零C98char str[20]{};//置零C11 引入全局 / 静态数组char str[20];定义在函数外部无需手动赋值会自动全部置零。English: Local variables are allocated on the stack, and stack memory is not cleared automatically by the compiler.局部变量分配在栈内存栈内存不会由编译器自动清零。English: If you writechar str[20] {0};, only the first element is set to 0, and all remaining elements are zero-initialized implicitly.如果写char str[20] {0};仅第一个元素显式设为 0剩余所有元素会被隐式初始化为 0。静态成员变量类内声明类外定义为什么不用构造函数初始化化静态成员变量因为静态成员变量可以直接用类名访问不需要依赖对象这时候不经过构造函数没有采用构造函数内的初始化条件sizeof(空类)1每个对象都应该在内存上有独一无二的地址不要重载和||逻辑与和逻辑或 无法模拟其短路特性operator和operator||的操作数是对象而不是表达式需要先得到/计算出具体的对象才能进行因此无法短路singleton中从指针拿到单例对象的引用singleton模式的类class Printer 的唯一 static Printer * printer;用引用方式取得 Printer ref_printer * printer; 这就从指针拿到了对象可以使用对象来调用重载函数例如打印函数的成员函数operator() 可以直接使用operator 自赋值判断 thisperson若为自赋值则可能会导致误删自己的内存这是无法恢复的要记得return *this值初始化 (value‑initialization) new int[10] ();基础数据类型Tnew T)[10 ] (); ()可以初始化为0这是C98的标准写与类的默认构造一致基础数据类型也可以这样newint[10];// 默认初始化newint[10]();// 值初始化newint[10]{};// C11以后列表初始化对自定义类类型structA{intx;};A* arr new A[10]();中 ()触发值初始化会调用A()默认构造函数逐个构造对象。不带括号A* arr new A[10];同样调用默认构造类类型默认初始化与值初始化行为大多一致差异主要体现在内置基础类型。模拟实现vector不要全部初始化vector使用push_back()插入对象插入一个初始化一个即可没有必要在分配内存时对所有元素进行零初始化这样做会带来大量无用开销。std::vector的reserve()只会分配原始的、未初始化的内存块raw memory不会构造任何对象不会做零初始化等到push_back/emplace_back的时候再用定位 new在空闲内存上逐个构造对象。如果 reserve 分配内存的时候就把 capacity 全部的空间全部初始化 / 置零当 capacity 很大、实际 size 很小的时候会产生大量完全没有必要的构造、清零开销。vector 底层需要拿到原始、未初始化的内存只负责内存的申请对象构造推迟到 push_back。该结论针对reserve如果是vector(n)、resize(n)业务语义要求存在 n 个有效对象则必须完成对应对象构造。重载[]的operator[]一定要进行下标index的判断继承与类型转换向上转型基类指针/引用接收派生类对象protected/private继承阻断隐式向上转换不再满足is‑a语义。三种继承访问控制 向上隐式转换规则 表继承方式语法示例派生类内部基类成员可见性 (基类public→派生类中)派生类内部基类成员可见性 (基类protected→派生类中)派生类内部基类成员可见性 (基类private→派生类中)派生类对象 → 基类指针/引用 隐式向上转型解读/注释public公有继承class Derived : public Basepublicprotected不可见✅支持隐式向上转型满足经典is‑a语义派生类对象就是一种基类对象外部可以直接Base* p d;是多态的前提条件。protected保护继承class Derived : protected Baseprotectedprotected不可见❌禁止隐式向上转型可强制static_cast语义不是is‑a基类public全部降级为protected仅派生类、派生类的子类内部可以访问基类成员外部不能隐式转基类指针表达“实现复用”不是is‑a关系。private私有继承class Derived : private Baseprivateprivate不可见❌禁止隐式向上转型可强制static_cast语义不是is‑a基类全部成员降级为派生类private仅本派生类内部可用派生类的子类也无法访问基类成员纯粹为复用基类实现完全没有is‑a。向上转型隐式转换的本质C语法规则只有public继承才代表派生类是一种基类编译器自动允许隐转换protected/private继承代表“复用基类代码”不是is‑a编译器直接禁止隐式转换。static_castBase*(derived)强制转换语法上可以编译通过属于绕过继承访问权限但不代表is‑a业务上不要这么写private/protected继承设计本意就不是用来做向上转型。继承与多态三种继承与多态支持情况 表继承方式是否支持多态虚函数推荐程度语义关系关键说明、注意事项典型使用场景public公有继承✅支持多态⭐强烈推荐is‑a是一个只有public继承虚函数才能发挥多态效果允许隐式向上转型面向对象接口继承。接口抽象、虚函数多态、基类指针管理派生类对象。protected保护继承⚠️语法上虚函数仍存在但不能外部多态调用⚠️不推荐has‑a复用实现外部无法隐式向上转型无法通过基类指针触发多态仅派生类及其子类内部可以使用基类功能。极少使用需要让派生类及其子类复用基类实现对外屏蔽基类接口。private私有继承❌不支持对外多态❌不推荐has‑a复用实现虚函数仅在派生类内部可见外部无法通过基类指针调用多态行为等价于组合的一种替代方案。复用基类代码实现但完全对外隐藏基类所有接口优先使用**组合(包含对象成员)**替代私有继承。定位newplacement newcharbuf[100];T*pnew(buf)T(10);// Only construct object on buf, no memory allocation定位newplacement newC98 标准就已经存在。English: Placement new does NOT allocate any memory; it only invokes the constructor of T on the memory address you provide (here the address stored infinish).中文定位new不分配任何内存它只在你给定的内存地址此处是finish保存的地址上调用T的构造函数。arr decays to int*​intarr[10]{1,2,3};int(*arrx2)[10]arr;//errint(*arrx2)[10]arr;//correct form用数组指针强转可以将退化的数组指针 重新指向整个数组​
返回列表