### 前言 此文章用于记录自己学习C++ Primer Plus 5 的第二章学习记录,大多是深入了解C++库的源代码解析,现在还是小白,目前是配合ChatGPT的3.5模型进行学习记录。 **我本想继续翻阅,但是由于自身对于C++的陌生以及工程的大量,所以浅尝辄止,我希望等我学习的差不多的时候,我能够自己从零开始看,并且实现 ,同时我希望阅读STL源码刨析,但是还需要点时间** ### AI阅读文章总结 这篇文章是对C++ Primer Plus第二章的学习记录, 主要介绍了C++的正则表达式和标准库函数std::regex_replace的实现原理。 通过对源代码的解析,讲解了模板语法、静态断言、预处理编译和typedef别名定义等C++的基础知识。 此外,还提到了STL源码解析的学习计划。 #### std::regex_replace 函数原理 ```C++ // 尝试使用regex替换值 std::string cheese = "His X ,How are you?"; // 用于生成一个我们需要替换的字符串,其中X是我们需要替换的值 std::regex reg("X"); // 用于申明一个正则对象 std::string result = std::regex_replace(cheese, reg, "StarYuhen"); // 用于进行对象替换 std::cout << result << std::endl; // 最后输出 ``` 这里我们追寻一下源代码 ```c++ template inline basic_string<_Ch_type, _St, _Sa> regex_replace(const basic_string<_Ch_type, _St, _Sa>& __s, const basic_regex<_Ch_type, _Rx_traits>& __e, const _Ch_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_Ch_type, _St, _Sa> __result; regex_replace(std::back_inserter(__result), __s.begin(), __s.end(), __e, __fmt, __flags); return __result; } ``` 这是其中regex_replace的语法构成,我们逐步分析,由于前面的一篇文章,我们已经讲述了模板语法的内容,这里就不做讲解了。 ```C++ template inline basic_string<_Ch_type, _St, _Sa> ``` 这一段就是通俗的模板语法,并且使用inline插入代码到函数位置减少开销,也在上文提到过 --- **开始解析:** 首先看这一段的代码: ```c++ regex_replace(const basic_string<_Ch_type, _St, _Sa>& __s, const basic_regex<_Ch_type, _Rx_traits>& __e, const _Ch_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) ``` 这里的传参列表一: * const basic_string<_Ch_type, _St, _Sa>& __s 他的意思是定义一个引用类型的参数__s,表示模板字符串的引用 basic_string<_Ch_type, _St, _Sa>& ,我们查看源代码: ```c++ template class basic_string ``` 在这里我们会发现这个类的模板语法定义的传参分别是 _CharT(字符串的字符类型), _Traits(字符串的分配器类型), _Alloc(字符串的储存方式). --- **扩展知识~:** 从刚才的源码查找我们会发现下面一段特殊的代码: ```c++ #if __cplusplus < 201103L typedef iterator __const_iterator; #else typedef const_iterator __const_iterator; #endif ``` 这是C++的预条件处理编译(预处理器的条件编译),#if,#else,#endif 应该都能看懂吧. 预条件处理编译能够根据特定的条件选择是否编译对应代码,可以让程序更加灵活和可移植。 而typedef用于定义别名的关键字 --- 这里的传参列表二: * const basic_regex<_Ch_type, _Rx_traits>& __e 这里我们跳转源代码看看: ```c++ template> class basic_regex { public: static_assert(is_same<_Ch_type, typename _Rx_traits::char_type>::value, "regex traits class must have the same char_type"); ``` 这里我们引用新的知识 static_assert 语句,他是一个编译时断言,和Java的Test测试库中的Assert类似。 is_same<_Ch_type, typename _Rx_traits::char_type>::value 的意思是判断_Ch_type和_Rx_traits::char_type 是否相同 --- 这里的传参列表三: * const _Ch_type* __fmt, 他是用于替换字符串的格式,你可以把他看作这个语句最重要的部分,它可以看作是一个正则的格式化语句. 而后我面我翻阅源码发现_Ch_type的定义: ```c++ template class regex_traits { public: typedef _Ch_type char_type; typedef std::basic_string string_type; typedef std::locale locale_type; ``` 从语法上我们看出 * char_type是_Ch_type的别名,同时理解为字符类型 * string_type 是std::basic_string模板的类型,被称为字符串类型 * locale_type则是std::locale的别名,他又是本地化类型 **我本想继续翻阅,但是由于自身对于C++的陌生以及工程的大量,所以浅尝辄止,我希望等我学习的差不多的时候,我能够自己从零开始看,并且实现 ,同时我希望阅读STL源码刨析,但是还需要点时间** --- 传参三: * regex_constants::match_flag_type __flags = regex_constants::match_default 他定义了他为可选参数,这个我很新奇,因为还未在C++中学习过,于是我查找资料想要实现函数设置默认值的代码, 实现如下: ```c++ int FlagsDefault() { return 10 + 10; } // 默认值参数 int flagsInt(int Int = FlagsDefault()) { return Int+1; } main(){ // 输出默认值的函数 std::cout << flagsInt(10) << std::endl; } ``` 我们会发现,若是没有传入参数,会按照默认值进行+1,如何传入了值则会用传入值进行+1. --- **开始解析功能代码:** ```c++ basic_string<_Ch_type, _St, _Sa> __result; regex_replace(std::back_inserter(__result), __s.begin(), __s.end(), __e, __fmt, __flags); return __result; ``` 先申明一个空字符串,__result,而后使用regex_replace的重载函数并使用std::back_inserter迭代器 逐渐增加到__result中,可以看作是++操作。 翻阅源代码发现一个新的关键字: ```c++ /// The only way to create this %iterator is with a container. explicit _GLIBCXX20_CONSTEXPR back_insert_iterator(_Container& __x) : container(std::__addressof(__x)) { } ``` explicit 关键字为修饰词,这个关键字告诉编译器他不能被隐性转换。 其他更深入的知识暂时了解不到,所以目前收获就这些。 Loading... ### 前言 此文章用于记录自己学习C++ Primer Plus 5 的第二章学习记录,大多是深入了解C++库的源代码解析,现在还是小白,目前是配合ChatGPT的3.5模型进行学习记录。 **我本想继续翻阅,但是由于自身对于C++的陌生以及工程的大量,所以浅尝辄止,我希望等我学习的差不多的时候,我能够自己从零开始看,并且实现 ,同时我希望阅读STL源码刨析,但是还需要点时间** ### AI阅读文章总结 这篇文章是对C++ Primer Plus第二章的学习记录, 主要介绍了C++的正则表达式和标准库函数std::regex_replace的实现原理。 通过对源代码的解析,讲解了模板语法、静态断言、预处理编译和typedef别名定义等C++的基础知识。 此外,还提到了STL源码解析的学习计划。 #### std::regex_replace 函数原理 ```C++ // 尝试使用regex替换值 std::string cheese = "His X ,How are you?"; // 用于生成一个我们需要替换的字符串,其中X是我们需要替换的值 std::regex reg("X"); // 用于申明一个正则对象 std::string result = std::regex_replace(cheese, reg, "StarYuhen"); // 用于进行对象替换 std::cout << result << std::endl; // 最后输出 ``` 这里我们追寻一下源代码 ```c++ template<typename _Rx_traits, typename _Ch_type, typename _St, typename _Sa> inline basic_string<_Ch_type, _St, _Sa> regex_replace(const basic_string<_Ch_type, _St, _Sa>& __s, const basic_regex<_Ch_type, _Rx_traits>& __e, const _Ch_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_Ch_type, _St, _Sa> __result; regex_replace(std::back_inserter(__result), __s.begin(), __s.end(), __e, __fmt, __flags); return __result; } ``` 这是其中regex_replace的语法构成,我们逐步分析,由于前面的一篇文章,我们已经讲述了模板语法的内容,这里就不做讲解了。 ```C++ template<typename _Rx_traits, typename _Ch_type, typename _St, typename _Sa> inline basic_string<_Ch_type, _St, _Sa> ``` 这一段就是通俗的模板语法,并且使用inline插入代码到函数位置减少开销,也在上文提到过 --- **开始解析:** 首先看这一段的代码: ```c++ regex_replace(const basic_string<_Ch_type, _St, _Sa>& __s, const basic_regex<_Ch_type, _Rx_traits>& __e, const _Ch_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) ``` 这里的传参列表一: * const basic_string<_Ch_type, _St, _Sa>& __s 他的意思是定义一个引用类型的参数__s,表示模板字符串的引用 basic_string<_Ch_type, _St, _Sa>& ,我们查看源代码: ```c++ template<typename _CharT, typename _Traits, typename _Alloc> class basic_string ``` 在这里我们会发现这个类的模板语法定义的传参分别是 _CharT(字符串的字符类型), _Traits(字符串的分配器类型), _Alloc(字符串的储存方式). --- **扩展知识~:** 从刚才的源码查找我们会发现下面一段特殊的代码: ```c++ #if __cplusplus < 201103L typedef iterator __const_iterator; #else typedef const_iterator __const_iterator; #endif ``` 这是C++的预条件处理编译(预处理器的条件编译),#if,#else,#endif 应该都能看懂吧. 预条件处理编译能够根据特定的条件选择是否编译对应代码,可以让程序更加灵活和可移植。 而typedef用于定义别名的关键字 --- 这里的传参列表二: * const basic_regex<_Ch_type, _Rx_traits>& __e 这里我们跳转源代码看看: ```c++ template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type>> class basic_regex { public: static_assert(is_same<_Ch_type, typename _Rx_traits::char_type>::value, "regex traits class must have the same char_type"); ``` 这里我们引用新的知识 static_assert 语句,他是一个编译时断言,和Java的Test测试库中的Assert类似。 is_same<_Ch_type, typename _Rx_traits::char_type>::value 的意思是判断_Ch_type和_Rx_traits::char_type 是否相同 --- 这里的传参列表三: * const _Ch_type* __fmt, 他是用于替换字符串的格式,你可以把他看作这个语句最重要的部分,它可以看作是一个正则的格式化语句. 而后我面我翻阅源码发现_Ch_type的定义: ```c++ template<typename _Ch_type> class regex_traits { public: typedef _Ch_type char_type; typedef std::basic_string<char_type> string_type; typedef std::locale locale_type; ``` 从语法上我们看出 * char_type是_Ch_type的别名,同时理解为字符类型 * string_type 是std::basic_string<char_type>模板的类型,被称为字符串类型 * locale_type则是std::locale的别名,他又是本地化类型 **我本想继续翻阅,但是由于自身对于C++的陌生以及工程的大量,所以浅尝辄止,我希望等我学习的差不多的时候,我能够自己从零开始看,并且实现 ,同时我希望阅读STL源码刨析,但是还需要点时间** --- 传参三: * regex_constants::match_flag_type __flags = regex_constants::match_default 他定义了他为可选参数,这个我很新奇,因为还未在C++中学习过,于是我查找资料想要实现函数设置默认值的代码, 实现如下: ```c++ int FlagsDefault() { return 10 + 10; } // 默认值参数 int flagsInt(int Int = FlagsDefault()) { return Int+1; } main(){ // 输出默认值的函数 std::cout << flagsInt(10) << std::endl; } ``` 我们会发现,若是没有传入参数,会按照默认值进行+1,如何传入了值则会用传入值进行+1. --- **开始解析功能代码:** ```c++ basic_string<_Ch_type, _St, _Sa> __result; regex_replace(std::back_inserter(__result), __s.begin(), __s.end(), __e, __fmt, __flags); return __result; ``` 先申明一个空字符串,__result,而后使用regex_replace的重载函数并使用std::back_inserter迭代器 逐渐增加到__result中,可以看作是++操作。 翻阅源代码发现一个新的关键字: ```c++ /// The only way to create this %iterator is with a container. explicit _GLIBCXX20_CONSTEXPR back_insert_iterator(_Container& __x) : container(std::__addressof(__x)) { } ``` explicit 关键字为修饰词,这个关键字告诉编译器他不能被隐性转换。 其他更深入的知识暂时了解不到,所以目前收获就这些。 最后修改:2023 年 04 月 07 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 1 如果觉得我的文章对你有用,请随意赞赏
1 条评论
测试邮件发送是否成功