В чем разница между использованием * и & для сравнения значений на равенство? - PullRequest
0 голосов
/ 06 октября 2018

Мне кажется, я понимаю, что на очень высоком уровне разница между & и * в Rust в том, что касается управления памятью.

В чем разница между следующими фрагментами кода.Есть ли опасность применения одного подхода по сравнению с другим?

for (i, item) in bytes.iter().enumerate() {
    if *item == b' ' {
        return i;
    }
}
for (i, &item) in bytes.iter().enumerate() {
    if item == b' ' {
        return i;
    }
}
for (i, item) in bytes.iter().enumerate() {
    if item == &b' ' {
        return i;
    }
}

Насколько я понимаю, когда я возвращаю значение из iter(), я возвращаю ссылку на элемент, найденный вbytes.Если я хочу сравнить элемент, мне нужно либо сравнить две ссылки &u8, либо сделать &item ссылку самой, чтобы при вызове item она имела тип u8, илиМне нужно разыменовать item, когда я сравниваю его так, чтобы item = &u8 -> *item = u8.

  1. Когда я запускаю код, используя (i, &item), когда я позже позвоню item, это то же самое, что разыменование во втором примере, или есть принципиальная разница в том, как компилятор интерпретирует первый фрагмент кода и второй фрагмент кода?

  2. Что-то не так с третьим фрагментом кода?Я понимаю, что это вопрос, основанный на мнении.Я понимаю, что если бы я присвоил значение другой переменной, используя item (или *item, или присвоив значение в качестве ссылки), у меня были бы другие типы данных, которые будут возвращены позже.Помимо управления типами данных, есть ли еще что-то, о чем следует помнить при рассмотрении вопроса о том, является ли item == &b' ' подходящим инструментом для работы?

1 Ответ

0 голосов
/ 06 октября 2018

Нет никакой разницы между этими фрагментами.Они генерируют точно такую ​​же сборку :

pub fn a(bytes: &[u8]) -> usize {
    for (i, item) in bytes.iter().enumerate() {
        if *item == b' ' {
            return i;
        }
    }
    0
}

pub fn b(bytes: &[u8]) -> usize {
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i;
        }
    }
    0
}

pub fn c(bytes: &[u8]) -> usize {
    for (i, item) in bytes.iter().enumerate() {
        if item == &b' ' {
            return i;
        }
    }
    0
}
playground::a:
    negq    %rsi
    movq    $-1, %rax

.LBB0_1:
    leaq    (%rsi,%rax), %rcx
    cmpq    $-1, %rcx
    je  .LBB0_2
    cmpb    $32, 1(%rdi,%rax)
    leaq    1(%rax), %rax
    jne .LBB0_1
    retq

.LBB0_2:
    xorl    %eax, %eax
    retq

; The code is identical so we just call the existing function
playground::b:
    jmp playground::a@PLT

; The code is identical so we just call the existing function
playground::c:
    jmp playground::a@PLT

Для чего бы это ни стоило, я написал бы функцию как

pub fn a(bytes: &[u8]) -> Option<usize> {
    bytes.iter().position(|&b| b == b' ')
}

iter() [...] ссылка на элемент, найденный в bytes

Да, iter обычно является функцией, которая возвращает итератор ссылок.

Мне нужно либо сравнить между

Как правило, вам нужно сравнивать две вещи с одинаковым количеством ссылок или иногда с одним уровнем разности ссылок.То, как вы этого достигнете, не имеет значения - ссылка на значение или разыменование другого, или разыменование с помощью * в качестве выражения или с помощью & в шаблоне.

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...