在这里插入图片描述

大家好,我是Halcyon.平安

欢迎文末添加好友交流,共同进步!

在这里插入图片描述


目录

C++中 define 和 const 的区别?

  • define 是预处理阶段的宏定义,可以是宏常量也可以是带参宏函数,由预处理器做简单的文本替换,没有类型检查
  • const 是编译阶段定义的"只读变量",有类型、会进符号表、可以调试
对比项 define const
处理阶段 预处理 编译
类型检查 无,纯文本替换 有,编译器会检查类型
内存 不分配内存(就地展开) 通常要分配内存
作用域 从定义处到文件尾,除非 #undef 受作用域限制(类、函数、文件)
调试 不能(预处理后宏名就没了) 可以看到变量名

(我觉得如果问到了的话,可以主动延伸const,比如Day1——修饰变量,修饰指针,修饰成员变量,修饰引用等等)


C++ 中 char*、const char*、char* const、const char* const 的区别?

记忆口诀:const 在 * 左边修饰"指向的内容",在 * 右边修饰"指针本身"

  • char*:普通字符指针,指向和内容都能改
  • const char*(等价于 char const*):能改指向,不能改内容
  • char* const不能改指向,能改内容
  • const char* const指向和内容都不能改

C++中 inline的作用?它有什么优缺点?

  • 作用:建议编译器把函数调用处直接展开成函数体,省去函数调用的开销(压栈、跳转、返回)
  • 优点:避免函数调用开销,提高执行效率(适合短小、频繁调用的函数)
  • 缺点
    • 代码膨胀(每处调用都展开一份),可能影响指令缓存命中率
    • 如果函数太大或递归,编译器会拒绝 inline,建议只是"建议"
    • 修改 inline 函数后所有调用它的地方都得重新编译
  • 注意点
    • inline 只是对编译器的建议,最终是否展开由编译器决定
    • C++17 起可以用 inline 定义变量(inline 变量)
    • 在类内定义的成员函数隐式 inline

C++中数组和指针的区别?

  • 数组:一段连续的内存,数组名可以看作首元素地址,但数组名本身不是指针(不能自增、不能重新赋值)
  • 指针:一个变量,存的是某块内存的地址
对比项 数组 指针
sizeof 得到整个数组占的字节数 得到指针本身大小(4/8 字节)
内存 连续 不一定连续
可修改性 数组名不能重新指向 可以随意改指向
传参 大多数情况会退化成指针 本身就是指针

C++中sizeof 和 strlen的区别?

  • sizeof 是运算符,求的是类型/变量占的内存大小(编译期就确定,包含结尾 '\0'
  • strlen 是函数,求的是字符串实际长度(运行时算,遇到 '\0' 停止,且不包含 '\0'
const char* s = "hello";
sizeof(s);     // 指针大小,通常 8
sizeof("hello"); // 6(5 个字符 + '\0')
strlen(s);     // 5

C++中extern有什么作用?extern"C"有什么作用?

  • extern:声明一个在别处定义过的变量/函数,告诉编译器"这个符号在别的地方有定义,链接时再去找",常用于跨文件使用全局变量
  • extern “C”:告诉 C++ 编译器按 C 的风格编译这一段代码。因为 C++ 编译时会对函数名做名字修饰(name mangling),C 不会,混编时链接不上。常见用法:
#ifdef __cplusplus
extern "C" {
#endif

void c_func(int a, int b);   // 按 C 风格编译,方便 C 代码调用

#ifdef __cplusplus
}
#endif

C++ 中 explicit 的作用?

  • 用在单参数构造函数(或 C++11 后所有但有一个参数的构造函数)前面,禁止编译器做隐式类型转换,只允许显式调用
  • 场景:避免一些不期望的自动转换带来意外行为
class A {
public:
    explicit A(int x) {}
};

A a1(10);   // OK,显式构造
A a2 = 10;  // 编译报错,因为没有 explicit 才允许这种隐式转换

C++中 final关键字的作用?

  • 修饰类:这个类不能再被继承
  • 修饰虚函数:这个虚函数不能再被派生类 override
class Base final {};        // Base 不能被继承

class Derived : public Base {
    virtual void f() final; // 派生类再 override f 就会报错
};

C++中野指针和悬挂指针的区别?

  • 野指针未初始化的指针,随机指向一块内存,那块内存可能根本不存在或没权限访问
  • 悬挂指针(dangling pointer):指针本来指向一块合法内存,但那块内存已经被释放/回收了,指针还保存着旧地址,再去访问就是未定义行为
int* p;          // 野指针,没初始化
int* q = new int(1);
delete q;
*q;              // 悬挂指针,q 指向的内存已经被 delete 了

避免方法:指针定义时初始化(nullptr),释放后立刻置空。


什么是内存对齐?为什么要内存对齐?

点击查看——结构体 / 内存对齐详解

  • 是什么:编译器在分配内存时,会按照一定的对齐倍数(通常是成员大小或平台默认对齐值)来摆放数据,让数据的地址是其大小的整数倍,中间可能填充空字节
  • 为什么要对齐
    • 硬件原因:CPU 读取内存是按字长(4/8 字节)成块读取的,不对齐可能要读两次再拼,效率低
    • 平台原因:某些平台(ARM 等)不对齐会直接硬件异常 crash
    • 缓存友好:对齐的数据更可能落在同一缓存行里
  • 怎么对齐(结构体规则):每个成员按其自身大小对齐,整个结构体大小是最大成员对齐值的整数倍
struct A {
    char c;   // 1 字节
             // 填充 3 字节
    int  i;   // 4 字节
};  // sizeof(A) = 8,而不是 5
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐