C++关键字解析
1.sizeof
和strlen
的区别
strlen
测量的是字符串的实际长度,源代码如下
1 | size_t strlen(const char *str) { |
sizeof
测量的是对象或者表达式类型占用的字节大小
总而言之,一个测量的是实际长度,到’/0’结束,而另一个则是测量实际占用的大小。
2.static的用法
应用场景 | 类型 | 作用 |
---|---|---|
局部 static 变量 |
函数内部 | 变量生命周期贯穿整个程序,但作用域仅限函数 |
文件内部 static 变量 |
文件作用域 | 限制变量可见性,避免命名冲突 |
文件内部 static 函数 |
文件作用域 | 仅在当前编译单元可见,隐藏实现细节 |
类的 static 变量 |
类成员 | 所有对象共享 |
类的 static 函数 |
类成员 | 不依赖对象,访问静态数据 |
静态工具类 | = delete |
防止实例化 |
线程安全的 static 变量 |
C++11 | 确保多线程环境下安全初始化 |
static
的核心作用: ✅ 控制作用域(文件/函数级别)
✅ 延长生命周期(局部 static
变量)
✅ 共享数据(类 static
成员)
✅ 提升封装性(防止全局变量污染)
3.const的用法
用法 | 作用 |
---|---|
const int a = 10; |
常量变量,不可修改 |
const int* p; |
指针指向的值不可修改 |
int* const p; |
指针本身不可修改 |
const int* const p; |
指针本身和指向的值都不可修改 |
void func(const int x); |
传值参数不可修改 |
void func(const int* p); |
传指针参数,指向的值不可修改 |
void func(const int& ref); |
传引用参数,引用值不可修改 |
class A { const int data; }; |
类的成员变量不可修改,需构造函数初始化 |
void show() const; |
const 成员函数,不能修改类成员变量 |
const int& getData() const; |
const 返回值,防止修改 |
4.const和define的区别
特性 | #define |
const |
---|---|---|
作用 | 预处理文本替换 | 定义常量变量 |
类型检查 | ❌ 无类型检查,可能引发错误 | ✅ 有类型检查,更安全 |
作用域 | ❌ 无作用域,作用于整个文件 | ✅ 遵循 C++ 作用域规则 |
内存占用 | ❌ 仅进行文本替换,不占用变量存储空间 | ✅ 变量存储在只读数据区 |
可调试性 | ❌ 不能在调试器中查看 | ✅ 可以查看变量值 |
const 指针支持 |
❌ 不能用于指针 | ✅ 可用于指针,如 const int* p |
适用场景 | 定义简单的文本宏(如 #define DEBUG ) |
定义具有类型的常量 |
在C++11之后,推荐使用constexpr
来完成一些define定义的值。意味编译时常量,在编译时完成计算来提高程序性能
5.inline函数的作用和使用
inline
关键字用于建议编译器在调用处直接展开函数代码,以减少函数调用的开销,提高运行效率。它适用于短小、频繁调用的函数。
类内部定义的函数默认是inline
的
1 | class Math { |
6.malloc
和new
的区别
特性 | new / new[] |
malloc() / calloc() |
---|---|---|
语言 | C++ | C(C++ 兼容) |
分配类型 | 适用于对象,调用构造函数 | 仅分配原始内存,不会调用构造函数 |
释放方式 | delete / delete[] |
free() |
返回类型 | 直接返回正确类型指针 | 返回 void* ,需要手动转换类型 |
初始化 | new 会初始化对象(默认构造或指定初始化) |
malloc 不会初始化(calloc 会零初始化) |
异常处理 | new 失败时抛出 std::bad_alloc 异常 |
malloc 失败时返回 NULL ,需要手动检查 |
安全性 | 更安全,支持 RAII(如 std::unique_ptr ) |
可能导致类型错误,易发生内存泄漏 |
7.free和delete的区别
特性 | delete / delete[] |
free() |
---|---|---|
适用语言 | C++ | C(C++ 兼容) |
适用对象 | new 分配的对象 |
malloc/calloc/realloc 分配的内存 |
析构函数 | ✅ 调用析构函数 | ❌ 不会调用析构函数 |
作用范围 | 对象销毁 + 释放内存 | 仅释放内存 |
使用方式 | delete p; / delete[] p; |
free(p); |
安全性 | 更安全,支持类对象的管理 | 仅适用于 C 语言风格的内存管理 |
类型安全 | 不需要强制转换 | 需要强制转换 void* |
8.volatile
关键字的使用与场景
volatile
关键字在编程中用于确保变量的可见性和防止编译器优化,其核心作用是告诉编译器每次访问变量时必须直接从内存中读取或写入,而不是使用寄存器中的缓存值。常用于嵌入式开发从硬件寄存器中读取数据
作用:
- 禁止编译器优化
确保每次对变量的读写操作都直接作用于内存,而非寄存器中的临时值,避免因优化导致意外行为。 - 保证可见性
当变量可能被外部因素(如硬件、其他线程、信号处理函数)修改时,确保程序能读取到最新值
9.C语言中struct
和CPP语言中struct
的区别
特性 | C语言中的 struct |
C++中的 struct |
C++中的 class |
---|---|---|---|
默认访问控制 | 公有 (public) | 公有 (public) | 私有 (private) |
成员函数 | 不支持 | 支持 | 支持 |
构造函数和析构函数 | 不支持 | 支持 | 支持 |
继承和多态 | 不支持 | 支持 | 支持 |
简单来说,C++中的struct
和class
非常相似,区别主要在于默认的访问控制权限,struct
默认是public
,而class
默认是private
。(在继承的时候也是如此)因此struct被用于保存数据结构,而class则用于描述抽象对象。
10.extern关键字
extern
是 C 和 C++ 中的一个关键字,主要用于声明变量或函数的外部链接,意味着该变量或函数是在其他地方定义的,而不是当前文件中定义的。
11.explicit关键字
用来声明类构造函数是显式调用的,而非隐式调用,可以阻止调用构造函数时进行隐式转换和赋值初始化。只可用于修饰单参构造函数,因为无参构造函数和多参构造函数本身就是显式调用的,再加上 explicit
关键字也没有什么意义。
声明 explicit
的构造函数,从而可以阻止编译器执行非预期 (往往也不被期望) 的类型转换,因为某些非预期的类型转换可能会引起意向不到的错误。
举例:
1 |
|
12.#define
vs typedef
特性 | #define | typedef |
---|---|---|
本质 | 预处理指令,文本替换 | 类型定义,编译时处理 |
类型检查 | 无类型检查,仅仅是字符串替换 | 受C语言类型系统约束,更加安全 |
指针类型 | 可能导致意外错误(如 INT_PTR a, b ) |
遵循类型规则(如 INT_PTR_T a, b ) |
适用场景 | 定义常量、宏函数 | 定义类型别名,适用于结构体、指针等 |
可调试性 | 代码不易调试(文本替换可能引入问题) | 更加直观,类型更加明确 |
- 使用
#define
仅当你需要定义常量或者宏函数时,如#define PI 3.14
。 - 使用
typedef
适用于定义复杂类型的别名,如typedef struct
、指针、数组等。
因此,typedef
在处理类型时比 #define
更安全、直观,而 #define
更适用于常量和宏。
13.memmove
memmove
是 C 标准库中的一个内存操作函数,声明在 <string.h>
头文件中。它的作用是将一块内存区域的数据复制到另一块内存区域,即使两块区域存在重叠,也能保证数据不会被破坏。因为在发生重叠的时候,就开始倒序复制,就可以避免这个问题
14.auto类型推导
(1) auto
类型推导规则
auto
根据右值类型推导,但去掉const
和引用。- 即基础类型推导,推导结果和初始化表达式一致,忽略引用和const修饰符。如果要保留这些特性,那么需要加上
&
和const
- 即基础类型推导,推导结果和初始化表达式一致,忽略引用和const修饰符。如果要保留这些特性,那么需要加上
auto&
保持引用类型,适用于引用变量。const auto&
可保持const
限定,避免去掉const
。auto*
适用于指针类型,但const
规则同样适用。decltype(auto)
会保持表达式的原始类型。
(2) auto
vs decltype(auto)
表达式 | 推导类型 |
---|---|
auto x = a; (a 是 const int ) |
int |
auto& x = a; |
int& |
const auto x = a; |
const int |
decltype(auto) x = a; |
const int |
decltype(auto) x = b; (b 是 int& ) |
int& |
C++ 的 auto
极大地增强了代码的简洁性,同时遵循模板推导规则,可以合理地推导类型,减少冗余代码。但在使用时,仍需注意 const
、引用和指针的影响,以避免意外的类型变更