@bit::Shadow
✧(≖ ◡ ≖✿
目录
[1. 什么是"别名(Alias)"问题?](#1. 什么是“别名(Alias)”问题?)
[2. restrict 如何解决这个问题?](#2. restrict 如何解决这个问题?)
[enum class强类型枚举C++11](#enum class强类型枚举C++11)
[enum class 的解决方案](#enum class 的解决方案)
[uint32_t 及 u_int32_t](#uint32_t 及 u_int32_t)
restrict修饰指针类型
是C99引入的关键字表示这个指针是访问其指向数据的唯一方式。
1. 什么是"别名(Alias)"问题?
看一个简单的例子,假设有两个指针 a 和 b:
void func(int *a, int *b) {
*a = 10;
*b = 20;
*a = *a + 5; // 这里的 *a 需要重新从内存读取吗?
}
-
编译器不知道
a和b是否指向同一块内存。 -
如果
a == b(即指向同一个地址),那么*b = 20会改变*a的值。 -
所以编译器必须保守地 认为
a和b可能重叠,每次使用*a时都要重新从内存读取,而不能直接用寄存器里缓存的旧值。
这种"保守"策略会++阻止编译器进行优化++。
2. restrict 如何解决这个问题?
c
void func(int *restrict a, int *restrict b) {
*a = 10;
*b = 20;
*a = *a + 5; // 编译器知道 a 和 b 不重叠,所以可以直接用寄存器里的 10
}
-
程序员通过
restrict向编译器做出承诺 :a和b++不会指向同一块内存++。 -
编译器收到这个承诺后,可以放心地优化:
- 在执行
*b = 20后,它知道*a没有被修改,所以可以直接用寄存器里的值(10)来计算*a + 5,无需重新从内存读取。
- 在执行
enum class强类型枚举C++11
原枚举体可能出现的问题(具体由环境决定)
1.命名空间污染
cpp
enum LogLevel
{
DEBUG,
INFO,
WARN,
ERROR,
FATAL
};
枚举体内定义的名字会转为"全局变量"。
2.隐式转换为整数
cpp
// ❌ 传统 enum
enum LogLevel {
DEBUG,
INFO,
WARNING,
ERROR,
FATAL
};
enum Fruit {
APPLE, // 冲突!APPLE 已经存在!!!
BANANA,
ORANGE
};
void func(LogLevel level) {}
int main() {
func(10); // ❌ 可以传入任意整数!
int x = WARNING; // ❌ 隐式转换为 int
x = x + 5; // ❌ 可以参与算术运算
if (INFO == 1) { // ❌ 可以与整数比较
// ...
}
return 0;
}
enum class 的解决方案
cpp
enum class LogLevel {
DEBUG,
INFO,
WARNING,
ERROR,
FATAL
};
void test(){
LogLevel lgLvel=LogLevel::DEBUG; // ✅ 必须加作用域
}
std::function<返回类型(参数列表)>
定义函数/函数对象
例如:
cpp
#include<functional>
using func_t = std::function<void()>;
std::function<void()>含义
void:返回类型为void。
():无参数。
含义:可以存储任何无参数、无返回值的函数/函数对象。
cpp
#include <functional>
#include <iostream>
// 普通函数
void hello() {
std::cout << "Hello, World!" << std::endl;
}
int main() {
std::function<void()> func = hello; // 存储普通函数
func(); // 调用:Hello, World!
return 0;
}
private函数无法被当做参数
uint32_t 及 u_int32_t
是一种类型别名,保证在任何平台下均为"32位无符号整数"(4字节)。保证了兼容性。再有:int8_t、uint64_t等扩展性C/C++类型,均是为了兼容平台。(正规C/C++标准)
注意:无ulong64_t。
除此之外还有u_int32_t 等相似形式,这是BSD系统标准,兼容性较差。对比如下
| 方面 | u_int32_t |
uint32_t |
|---|---|---|
| 来源 | BSD 系统(Unix 传统) | C99/C++11 标准 |
| 头文件 | <sys/types.h> |
<stdint.h>(C) <cstdint>(C++) |
| 标准化 | 非标准(BSD 扩展) | ✅ 标准(ISO C/C++) |
| 可移植性 | 主要 BSD/Linux 系统 | ✅ 所有支持 C99/C++11 的平台 |
| 命名风格 | u_ 前缀(BSD 风格) |
_t 后缀(标准风格) |
| 定义方式 | typedef unsigned int u_int32_t; |
typedef unsigned int uint32_t; |
string转换为char*、char*转换为string
cpp
char* name = _name.c_str();
char*转换为string可以隐式转换少用库函数实现。
关于void**
cpp
int main()
{
// printf("%d\n",ThreadModule::number);
//void**对地址的作用
// void a = 10;//wrong!!
int a = 10;
int* pa = &a;
printf("%p\n", pa);
printf("%p\n", (void*)pa);
// cout <<*(void*)pa);wrong 无法打印"空类型"
// printf("%p\n", **(void**)pa);
printf("%p\n", (void**)pa);//double转换为int可能值改变。此处不变是因为解析方式不变。
printf("%p\n", *(void**)pa);
return 0;
}
感谢支持,长期连载
欢迎关注
