2012-04-21 3 views
0

Я знаю, что shift, push и pop - это методы Array, используемые для добавления/удаления элементов массива, но я не уверен, что происходит в памяти. Скажем, например, метод pop, который удаляет последний элемент массива. Это напоминает мне порядок LIFO, используемый в стеке, но я предполагаю, что этот элемент на самом деле не «выскочил», как в программировании сборки; что индекс всего массива смещается. Я действительно не знаю, если бы кто-нибудь мог мне помочь, я бы очень признателен.Ruby: Shift, Push и Pop в памяти

ответ

5

Ruby предназначен для программистов, которые страдают от идеи, что у вас есть. Мы доверяем тем программистам, которые делают эту реализацию, что они могут сделать лучше всего в оптимизации производительности и управления памятью.

Если вы просто любопытно, вот код для массива # сдвига в Rubinius:

def shift(n=undefined) 
    Rubinius.check_frozen 

    if n.equal? undefined 
     return nil if @total == 0 
     obj = @tuple.at @start 
     @tuple.put @start, nil 
     @start += 1 
     @total -= 1 

     obj 
    else 
     n = Rubinius::Type.coerce_to(n, Fixnum, :to_int) 
     raise ArgumentError, "negative array size" if n < 0 

     slice!(0, n) 
    end 
end 

И вы можете видеть, уже сам по себе массив является Rubinius :: Кортеж, и в определении кортежа, то Rubinius :: Array. То, что он делает, просто помещает начальную позицию в следующую. Я не уверен, что они выпустят пространство, которое он использовал (что, как я полагаю, будет), потому что вам нужно копать глубже.

В официальном 1.9.3 я не знаю, как это реализовано, так как они делают это на C, и их трудно читать. Если вы хотите узнать более подробную информацию, вы можете разблокировать Rubinius на GitHub или разблокировать официальный 1.9.3 с ruby-lang.org и прочитать исходный код. Вы можете узнать больше о программировании C/C++ тоже :)


Так что я быстро прошел через код официальной 1.9.3, и это определение массива функция # сдвиг:

static VALUE 
rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) 
{ 
    VALUE result; 
    long n; 

    if (argc == 0) { 
    return rb_ary_shift(ary); 
    } 

    rb_ary_modify_check(ary); 
    result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST); 
    n = RARRAY_LEN(result); 
    if (ARY_SHARED_P(ary)) { 
    if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) { 
     rb_mem_clear(RARRAY_PTR(ary), n); 
    } 
     ARY_INCREASE_PTR(ary, n); 
    } 
    else { 
    MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n); 
    } 
    ARY_INCREASE_LEN(ary, -n); 

    return result; 
} 

Это line:

MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n); 

Это говорит нам, что он фактически перемещает смещение блока памяти на n. Вероятно, поэтому чиновник работает медленнее Рубиния ... Рубиний использует большую память, но экономит время; чиновник потребляет меньше памяти, но занимает больше времени ...

+0

плохо проверить исходный код c. мне любопытно. –

+0

@BhubhuHbuhdbus Небольшие обновления :) Я тоже прошел код C. – texasbruce

Смежные вопросы