在这两种情况下,我想知道在#gsub调用期间字符串对象的内部字符串缓冲区是如何更新的:
"hello".gsub!('r', 'a')
。"hello".gsub!('e', 'a')
。在这两种情况下,将#gsub创建一个新的字符串缓冲区,将原始缓冲区复制到新的缓冲区,然后扔掉原来的?或者替换是否就地完成?
答案 0 :(得分:3)
根据最后一个参数,MRI只有一种方法str_gsub
可以同时处理gsub
和gsub!
:
static VALUE str_gsub(int argc, VALUE *argv, VALUE str, int bang)
如果找不到匹配项,则方法只返回nil
(gsub!
)或字符串副本(gsub
):
beg = rb_reg_search(pat, str, 0, 0);
if (beg < 0) {
if (bang) return Qnil; /* no match, no substitution */
return rb_str_dup(str);
}
否则,将创建一个新的字符串缓冲区:
dest = rb_str_buf_new(blen);
然后执行替换,然后替换字符串(gsub!
)或返回新实例(gsub
):
if (bang) {
rb_str_shared_replace(str, dest);
}
else {
RBASIC(dest)->klass = rb_obj_class(str);
OBJ_INFECT(dest, str);
str = dest;
}
if (tainted) OBJ_TAINT(str);
return str;