1

我想确切地知道在这两种情况下 #gsub 调用期间如何更新字符串对象的内部字符串缓冲区:

  1. 没有进行替换。例如"hello".gsub!('r', 'a').
  2. 搜索字符串和替换字符串的字节长度完全相同。例如,"hello".gsub!('e', 'a')

在这两种情况下,#gsub 会不会创建一个新的字符串缓冲区,将原来的缓冲区复制到新的缓冲区,然后扔掉原来的?还是会在原地完成替换?

4

1 回答 1

3

MRI 有一种方法str_gsub可以同时处理gsubgsub!,具体取决于最后一个参数:

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;
于 2013-10-13T06:28:32.713 回答