前言
此文章用于记录自己学习C++ Primer Plus 5 的第二章学习记录,大多是深入了解C++库的源代码解析,现在还是小白,目前是配合ChatGPT的3.5模型进行学习记录。
**我本想继续翻阅,但是由于自身对于C++的陌生以及工程的大量,所以浅尝辄止,我希望等我学习的差不多的时候,我能够自己从零开始看,并且实现
,同时我希望阅读STL源码刨析,但是还需要点时间**
AI阅读文章总结
这篇文章是对C++ Primer Plus第二章的学习记录,
主要介绍了C++的正则表达式和标准库函数std::regex_replace的实现原理。
通过对源代码的解析,讲解了模板语法、静态断言、预处理编译和typedef别名定义等C++的基础知识。
此外,还提到了STL源码解析的学习计划。
std::regex_replace 函数原理
// 尝试使用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; // 最后输出
这里我们追寻一下源代码
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的语法构成,我们逐步分析,由于前面的一篇文章,我们已经讲述了模板语法的内容,这里就不做讲解了。
template<typename _Rx_traits, typename _Ch_type,
typename _St, typename _Sa>
inline basic_string<_Ch_type, _St, _Sa>
这一段就是通俗的模板语法,并且使用inline插入代码到函数位置减少开销,也在上文提到过
开始解析:
首先看这一段的代码:
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>& ,我们查看源代码:
template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string
在这里我们会发现这个类的模板语法定义的传参分别是
_CharT(字符串的字符类型),
_Traits(字符串的分配器类型),
_Alloc(字符串的储存方式).
扩展知识~:
从刚才的源码查找我们会发现下面一段特殊的代码:
#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
这里我们跳转源代码看看:
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的定义:
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++中学习过,于是我查找资料想要实现函数设置默认值的代码,
实现如下:
int FlagsDefault() {
return 10 + 10;
}
// 默认值参数
int flagsInt(int Int = FlagsDefault()) {
return Int+1;
}
main(){
// 输出默认值的函数
std::cout << flagsInt(10) << std::endl;
}
我们会发现,若是没有传入参数,会按照默认值进行+1,如何传入了值则会用传入值进行+1.
开始解析功能代码:
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中,可以看作是++操作。
翻阅源代码发现一个新的关键字:
/// The only way to create this %iterator is with a container.
explicit _GLIBCXX20_CONSTEXPR
back_insert_iterator(_Container& __x)
: container(std::__addressof(__x)) { }
explicit 关键字为修饰词,这个关键字告诉编译器他不能被隐性转换。
其他更深入的知识暂时了解不到,所以目前收获就这些。
1 条评论
测试邮件发送是否成功