提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
-
- 问题1:`constexpr`与指针类型的关系(核心纠正误区)
-
- [1.1 先明确:`constexpr`指针的本质](#1.1 先明确:
constexpr指针的本质) - [1.2 分场景验证(结合你的例子)](#1.2 分场景验证(结合你的例子))
-
- [场景1:`Point*` 能否用`constexpr`?](#场景1:
Point*能否用constexpr?) - [场景2:`std::string*` 能否用`constexpr`?](#场景2:
std::string*能否用constexpr?)
- [场景1:`Point*` 能否用`constexpr`?](#场景1:
- [1.3 总结你的核心问题](#1.3 总结你的核心问题)
- [1.1 先明确:`constexpr`指针的本质](#1.1 先明确:
- 问题2:字符数组赋值汉字的问题
-
- [2.1 为什么`char arr[] = {'哈','哈','\0'}`会乱码?](#2.1 为什么
char arr[] = {'哈','哈','\0'}会乱码?) - [2.2 字符数组赋值汉字的正确手段(不止字符串形式)](#2.2 字符数组赋值汉字的正确手段(不止字符串形式))
- [2.3 关键注意事项](#2.3 关键注意事项)
- 总结
- [2.1 为什么`char arr[] = {'哈','哈','\0'}`会乱码?](#2.1 为什么
c
最后两个问题
1、关于constexpr
你上面提到了并非基础类型支持constexpr,自定义类型构造函数支持constexpr,这种类型就支持constexpr,
以及char支持,char*也支持,那么上面的point结构体构造函数支持constexpr,那么point支持,point*类型也就支持是吗,
之前你提到过std::string不支持constexpr,那么std::string*是不是也不支持,
一种数据类型支持,这种数据类型指针类型就支持,
反之,这种数据类型不支持,这种数据类型对应的指针类型也不支持是吗
2、关于字符数组赋值汉字
char arr[]="哈哈"赋值之后可以正确使用
char arr[] = {'哈','哈','\0'}这种就乱码,是不是字符数组赋值汉字只能用char arr[]="哈哈"形式,还有其他手段吗
你现在想确认两个核心问题:一是constexpr与指针类型的关系(某类型支持constexpr则其指针也支持?反之则不支持?),包括point*和std::string*的具体情况;二是字符数组用{}赋值汉字乱码的原因,以及除了字符串形式外是否有其他赋值手段。我会逐一拆解,纠正核心误区。
问题1:constexpr与指针类型的关系(核心纠正误区)
你的核心误区是:认为"某类型支持constexpr ↔ 该类型的指针也支持constexpr"------这个结论是错误的。
constexpr对指针类型的支持,核心看两个维度,和"指向的类型本身是否支持constexpr"无直接绑定关系:
- 指针类型本身能否被
constexpr修饰 :所有指针类型(不管指向什么)都可以被constexpr修饰; - 指针的初始化值是否是"编译期常量地址":这是能否编译通过的关键,和指向的类型无关。
1.1 先明确:constexpr指针的本质
constexpr修饰指针时,要求的是指针存储的地址值是编译期可确定的常量 ,而非"指向的对象是constexpr对象"(后者只是获取编译期地址的常见方式)。
1.2 分场景验证(结合你的例子)
场景1:Point* 能否用constexpr?
- 情况1:初始化地址是编译期常量 → 合法
cpp
struct Point {
constexpr Point(int x_, int y_) : x(x_), y(y_) {}
int x, y;
};
// 1. p是constexpr对象,地址&p是编译期常量 → Point*支持constexpr
constexpr Point p(10, 20);
constexpr Point* pp = &p; // 合法!pp是constexpr指针
// 2. nullptr是编译期常量 → 即使指向非constexpr类型,也合法
constexpr Point* pp2 = nullptr; // 合法!
- 情况2:初始化地址是运行期变量 → 非法
cpp
Point p2(30, 40); // p2是运行期对象,地址&p2是运行期确定
constexpr Point* pp3 = &p2; // 非法!编译报错(地址不是编译期常量)
场景2:std::string* 能否用constexpr?
首先明确:std::string(C++17及之前)的构造函数不是constexpr,所以无法创建constexpr的std::string对象,但**std::string*指针本身可以被constexpr修饰**,只要初始化地址是编译期常量:
cpp
// 情况1:初始化地址是nullptr(编译期常量)→ 合法
constexpr std::string* ps1 = nullptr; // 合法!
// 情况2:初始化地址是运行期std::string对象 → 非法
std::string s = "hello";
constexpr std::string* ps2 = &s; // 非法!编译报错(地址是运行期的)
// 补充:C++20开始,std::string支持constexpr,但核心逻辑不变
#if __cpp_lib_constexpr_string >= 201907L
constexpr std::string s_const = "hello"; // C++20+合法
constexpr std::string* ps3 = &s_const; // 合法!地址是编译期常量
#endif
1.3 总结你的核心问题
- ❌ 错误认知:"类型支持
constexpr→ 其指针也支持;类型不支持 → 指针也不支持" - ✅ 正确逻辑:
- 任何指针类型都可以被
constexpr修饰(语法上支持); - 能否编译通过,只看指针的初始化地址是否是编译期常量 (如
constexpr对象的地址、nullptr、字符串字面量地址); - 指向的类型是否支持
constexpr,只是"能否获取编译期地址"的条件之一,而非指针本身能否用constexpr的条件。
- 任何指针类型都可以被
问题2:字符数组赋值汉字的问题
2.1 为什么char arr[] = {'哈','哈','\0'}会乱码?
核心原因:单字符字面量'哈'在编译时会被编译器截断为1字节,丢失了汉字的多字节编码信息,导致数组中存储的是无效字节,自然乱码。
拆解过程(以UTF-8编码为例):
- "哈"的UTF-8完整编码是3字节:
0xE5 0x93 0x88; - 当你写
'哈'时,编译器无法把3字节塞进1个char,会截断 (通常取最后1字节),变成0x88; - 所以
char arr[] = {'哈','哈','\0'}实际存储的是:0x88, 0x88, 0x00→ 这不是"哈"的有效编码,输出自然乱码。
2.2 字符数组赋值汉字的正确手段(不止字符串形式)
字符串形式char arr[] = "哈哈"是最简洁的,但也有其他合法手段,核心是手动写入汉字的完整多字节编码(十六进制) ,而非直接写'哈'。
手段1:手动写入多字节编码({}形式,推荐)
cpp
#include <iostream>
using namespace std;
int main() {
// 方式1:UTF-8编码("哈"=0xE5 0x93 0x88)
char arr1[] = {0xE5, 0x93, 0x88, 0xE5, 0x93, 0x88, 0x00};
// 方式2:GBK编码("哈"=0xB9 0xFE)
char arr2[] = {0xB9, 0xFE, 0xB9, 0xFE, 0x00};
// 验证输出(需确保控制台编码匹配,比如UTF-8)
cout << arr1 << endl; // 输出:哈哈
// arr2需控制台设为GBK才会正常输出,UTF-8下会乱码
return 0;
}
手段2:运行期手动赋值字节
cpp
#include <iostream>
using namespace std;
int main() {
char arr3[10] = {0}; // 初始化全0
// 手动赋值UTF-8的"哈"
arr3[0] = 0xE5;
arr3[1] = 0x93;
arr3[2] = 0x88;
arr3[3] = 0xE5;
arr3[4] = 0x93;
arr3[5] = 0x88;
arr3[6] = 0x00;
cout << arr3 << endl; // 输出:哈哈
return 0;
}
手段3:使用宽字符/Unicode(更规范的多字符处理)
如果需要更通用的汉字处理,推荐用宽字符类型(wchar_t)或C++11的UTF-8字符串:
cpp
#include <iostream>
#include <locale> // 用于设置本地化
using namespace std;
int main() {
// 方式1:宽字符(wchar_t)
wchar_t w_arr[] = L"哈哈"; // L前缀表示宽字符字面量
wcout.imbue(locale("")); // 设置本地化,否则宽字符输出乱码
wcout << w_arr << endl; // 输出:哈哈
// 方式2:C++11 UTF-8字符串(推荐现代C++)
const char* u8_arr = u8"哈哈"; // u8前缀表示UTF-8字面量
cout << u8_arr << endl; // 输出:哈哈
return 0;
}
2.3 关键注意事项
- 所有手段的核心:汉字是多字节,必须保证字节数完整,且编码格式(UTF-8/GBK)和控制台/文件编码一致;
- 字符串形式
"哈哈"的优势:编译器自动解析编码并填充完整字节,无需手动写十六进制,是最省心的方式。
总结
constexpr与指针的核心逻辑:任何指针类型都可被constexpr修饰,能否编译通过仅看指针初始化地址是否为编译期常量,与指向的类型是否支持constexpr无直接绑定;- 字符数组赋值汉字的关键:不能直接用
'哈'(会截断),除了字符串形式,还可手动写入汉字的完整多字节编码(十六进制),或使用宽字符/UTF-8字面量。