C++常见避坑指南( 三 )

如果使用C++标准库来实现,常规写法可以参考下面:
#include <IOStream>#include <string>#include <locale>#include <codecvt>// 从窄字符串到宽字符串的转换std::wstring narrowToWide(const std::string& narrowStr) {    try {        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;        return converter.from_bytes(narrowStr);    } catch (...) { // 如果传进来的字符串不是utf8编码的,这里会抛出std::range_error异常        return {};    }}// 从宽字符串到窄字符串的转换std::string wideToNarrow(const std::wstring& wideStr) {    try {        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;        return converter.to_bytes(wideStr);    } catch (...) {        return {};    }}//utf8字符串转成stringstd::string utf8ToString(const char8_t* str) {    std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;    std::u16string u16str = convert.from_bytes(        reinterpret_cast<const char*>(str),        reinterpret_cast<const char*>(str + std::char_traits<char8_t>::length(str)));    return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(u16str);}int main(){    {        std::wstring wideStr = L"Hello, 你好!";        std::string narrowStr = wideToNarrow(wideStr);        std::wstring convertedWideStr = narrowToWide(narrowStr);    } {        //std::string narrowStr = "Hello, 你好!"; (1)        std::string narrowStr = utf8ToString(u8"Hello, 你好!"); //(2)        std::wstring wideStr = narrowToWide(narrowStr);        std::string convertedNarrowStr = wideToNarrow(wideStr);    }        return 0;}(1)首先std::string不理解编码,在CPP官方手册里面也解释了,std::string处理字节的方式与所使用的编码无关 , 如果用于处理多字节或可变长度字符的序列(例如 UTF-8) , 则此类的所有成员以及它的迭代器仍然以字节(而不是实际的编码字符)为单位进行操作,如果用来处理包含中文的字符串就可能出现乱码 。这里直接将包含中文的字符串赋值给std::string,无法保证是UTF8编码,进行转换时会提示std::range_error异常;此外,std::wstring是会理解编码的,其中的字符串通常使用 UTF-16 或 UTF-32 编码,这取决于操作系统和编译器的实现 。
(2)这里由于使用u8""构造了UTF8编码字符串,但是不能直接用来构造std::string,所以进行转了下utf8ToString;
全局静态对象大家有没有在工程代码中发现有下面这种写法,将常量字符串声明为静态全局的 。
static const std::string kVal="hahahhaha";
static const std::wstring kxxConfigVal="hahahhaha";
优点:
可读性好:使用有意义的变量名,可以清晰地表达变量的含义和用途,提高了代码的可读性 。
安全性高:由于使用了 const 关键字,这个字符串变量是不可修改的,可以避免意外的修改和安全问题 。
生命周期长:静态变量的生命周期从程序启动到结束 , 不受函数的调用和返回影响 。
缺点:
构造开销:静态变量的初始化发生在程序启动时也就是执行main()之前,会增加程序启动的时间和资源消耗 。大量的这种静态全局对象,会拖慢程序启动速度
静态变量共享:静态变量在整个程序中只有一份实例,可能会导致全局状态共享和难以调试的问题 。
此外 , 静态变量的初始化顺序可能会受到编译单元(源文件)中其他静态变量初始化顺序的影响,因此在跨编译单元的情况下,静态变量的初始化顺序可能是不确定的 。


推荐阅读