Нужно ли использовать usize для доступа к элементам вектора? - PullRequest
0 голосов
/ 30 мая 2018

У меня есть двумерный вектор, который отклоняет индексирование с использованием значений i32, но работает, если я приведу эти значения с использованием as usize:

#[derive(Clone)]
struct Color;

struct Pixel {
    color: Color,
}

fn shooting_star(p: &mut Vec<Vec<Pixel>>, x: i32, y: i32, w: i32, h: i32, c: Color) {
    for i in x..=w {
        for j in y..=h {
            p[i][j].color = c.clone();
        }
    }
}

fn main() {}

При компиляции я получаю сообщение об ошибке

error[E0277]: the trait bound `i32: std::slice::SliceIndex<[std::vec::Vec<Pixel>]>` is not satisfied
  --> src/main.rs:11:13
   |
11 |             p[i][j].color = c.clone();
   |             ^^^^ slice indices are of type `usize` or ranges of `usize`
   |
   = help: the trait `std::slice::SliceIndex<[std::vec::Vec<Pixel>]>` is not implemented for `i32`
   = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<std::vec::Vec<Pixel>>`

Если я поменяю код на

p[i as usize][j as usize].color = c.clone();

, тогда все работает нормально.Однако, кажется, что это будет действительно странный выбор без причины, по которой тип Vec не будет обработан.

В документации есть множество примеров, таких как

assert_eq!(vec[0], 1);

. Насколько я понимаю, если простое число без десятичной дроби по умолчанию является i32,тогда нет никакой причины использовать i32, чтобы индексирование не работало.

1 Ответ

0 голосов
/ 30 мая 2018

В отличие от Java, C # или даже C ++, числовые литералы в Rust не имеют фиксированного типа.Числовой тип литерала обычно определяется компилятором или явно указывается с использованием суффикса (0usize, 0.0f64 и т. Д.).В связи с этим типом литерала 0 в assert_eq!(vec[0], 1); является , выведенным , равным usize, поскольку Rust позволяет Vec индексировать только по номерам типа usize.

Что касается логического обоснования использования usize в качестве типа индексации: usize эквивалентно слову в целевой архитектуре.Таким образом, usize может ссылаться на индекс / адрес всех возможных областей памяти для компьютера, на котором запущена программа.Таким образом, максимально возможная длина вектора - это максимально возможное значение, которое может содержаться в isize (isize::MAX == usize::MAX / 2).Использование usize размеров и индексов для Vec предотвращает создание и использование вектора, большего, чем сама доступная память.

Кроме того, использование целого числа без знака, достаточно большого, чтобы ссылаться на все возможные области памятипозволяет удалить две динамические проверки: одну - предоставленный размер / индекс неотрицательный (если бы использовалось isize, эту проверку пришлось бы выполнять вручную), а две - создание вектора или разыменование значения векторане приведет к нехватке памяти на компьютере.Однако последнее гарантируется только тогда, когда тип, сохраненный в векторе, помещается в одно слово.

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