a = ''
и a.clear
делают несколько разные вещи.
a = ''
создает новый объект String
и присваивает его a
.Старый объект String
все еще перемещается в памяти, ожидая сбора мусора.
2.4.4 :010 > a = 'foo'
=> "foo"
2.4.4 :011 > a.object_id
=> 70311739468740
2.4.4 :012 > a = ''
=> ""
2.4.4 :013 > a.object_id
=> 70311748786840
Обратите внимание на различные идентификаторы объектов.
a.clear
очищает существующий объект String
.
2.4.4 :016 > a = 'foo'
=> "foo"
2.4.4 :017 > a.object_id
=> 70311748749240
2.4.4 :018 > a.clear
=> ""
2.4.4 :019 > a.object_id
=> 70311748749240
Обратите внимание, что идентификатор объекта такой же.
В частности clear
вызывает str_discard
, что немедленно освобождает память, выделенную для String
.
static inline void
str_discard(VALUE str)
{
str_modifiable(str);
if (!STR_EMBED_P(str) && !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
RSTRING(str)->as.heap.ptr = 0;
RSTRING(str)->as.heap.len = 0;
}
}
Другой способ увидеть разницу ...
2.4.4 :026 > a = 'foo'
=> "foo"
2.4.4 :027 > b = a
=> "foo"
2.4.4 :028 > a.object_id
=> 70311748602540
2.4.4 :029 > b.object_id
=> 70311748602540
a
и b
указывают на один и тот же базовый объект.
2.4.4 :030 > a = ''
=> ""
2.4.4 :031 > b
=> "foo"
2.4.4 :032 > a.object_id
=> 70311748541360
2.4.4 :033 > b.object_id
=> 70311748602540
После a = ''
, a
указывает на новый объект, а b
указывает на оригинал.Это показывает, почему a = ''
не может немедленно освободить память, что-то еще может ссылаться на оригинал String
.
Если мы настроим это снова ...
2.4.4 :034 > a = 'foo'
=> "foo"
2.4.4 :035 > b = a
=> "foo"
2.4.4 :036 > a.object_id
=> 70311748490260
2.4.4 :037 > b.object_id
=> 70311748490260
Но на этот раз используйтеa.clear
...
2.4.4 :038 > a.clear
=> ""
2.4.4 :039 > b
=> ""
2.4.4 :040 > a.object_id
=> 70311748490260
2.4.4 :041 > b.object_id
=> 70311748490260
a
и b
по-прежнему относятся к одному и тому же объекту.