Почему существуют неизменные ссылки на типы копий в ржавчине? - PullRequest
0 голосов
/ 12 октября 2019

Так что я только начал изучать ржавчину (первые несколько глав "книги") и, очевидно, я настоящий нуб. Я закончил главу «Основы владения» (4) и написал несколько тестовых программ, чтобы убедиться, что я все понял. Кажется, я разбираюсь с основами, но я спрашивал себя, почему неизменные ссылки на типы копий вообще возможны. Я попытаюсь объяснить мои мысли примерами.

Я подумал, что вы, возможно, захотите сохранить ссылку на тип копии, чтобы вы могли проверить его значение позже, вместо того, чтобы иметь копию старого значения, но это можетне может быть, поскольку базовое значение не может быть изменено, пока оно заимствовано.
Самым базовым примером этого будет следующий код:

let mut x = 10; // push i32
let x_ref = &x; // push immutable reference to x
// x = 100;        change x which is disallowed since it's borrowed currently
println!("{}", x_ref); // do something with the reference since you want the current value of x

Единственная причина, по которой я могув настоящее время я думаю (насколько мне известно), что они просто существуют, поэтому вы можете вызывать универсальные методы, для которых требуются ссылки (например, cmp).
Этот код демонстрирует это:

let x = 10;               // push i32
// let ordering = 10.cmp(x); try to compare it but you can't since cmp wants a reference
let ordering = 10.cmp(&x) // this works since it's now a reference

Итак, это единственная причина, по которой вы можете создавать неизменные ссылки на типы копий?

Отказ от ответственности:
Я не вижу Просто продолжайте читать книгу как правильный ответ. Однако я полностью понимаю, что если вы скажете что-то вроде Да, вам это нужно для этого и для этого варианта использования (необязательный пример), это будет описано в главе X . Я надеюсь, вы понимаете, что я имею в виду:)

РЕДАКТИРОВАТЬ:
Может быть стоит отметить, я программист C # и не новичок в самом программировании.

РЕДАКТИРОВАТЬ 2:
IНе знаю, технически ли это дубликат этого вопроса , но я не до конца понимаю вопрос и ответ, поэтому надеюсь на более простой ответ, понятный настоящему нубу .

Ответы [ 3 ]

1 голос
/ 12 октября 2019

Неизменная ссылка на Copy -тип все еще остается "неизменной ссылкой". Код, который передается по ссылке, не может изменить исходное значение. Он может сделать (мы надеемся) тривиальную копию этого значения, но он может изменить эту копию только после этого.

То есть, первоначальный владелец значения гарантирован, что - в то время как получатели ссылкиможет решить сделать копию и изменить это - состояние того, на что ссылаются, никогда не может измениться. Если получатель хочет изменить значение, он может чувствовать себя свободно;никто больше этого не увидит.

Неизменные ссылки на примитивы не отличаются, и, будучи повсюду Copy, вы, вероятно, более склонны к тому, что "неизменяемая ссылка" означает семантически для примитивных типов. Например,

fn print_the_age(age: &i32) { ... }

Эта функция может сделать копию с помощью *age и изменить ее. Но звонящий не увидит этого изменения, и в первую очередь это не имеет особого смысла.


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

Подумайте, откуда исходит ссылка: Если вы получаете &i32, откуда бы он ни исходил, он не может измениться и можетосвободить. «I32» может быть частью более крупного типа, который - из-за раздачи ссылки - не может перемещаться, изменяться или перераспределяться;получателю это гарантировано. Трудно сказать, что здесь есть преимущество;таким образом, было бы выгодно сообщать более подробные типовые (и целые!) отношения таким образом.

1 голос
/ 12 октября 2019

Они очень полезны, потому что они могут быть переданы универсальным функциям, которые ожидают ссылку:

fn map_vec<T, U>(v: &Vec<T>, f: impl Fn(&T) -> U) -> Vec<U> {...}

Если бы неизменные ссылки не-1004 * типов были запрещены, нам потребовалось бы две версии:

fn map_vec_own<T: !Copy, U>(v: &Vec<T>, f: impl Fn(&T) -> U) -> Vec<U> {...}
fn map_vec_copy<T: Copy, U>(v: &Vec<T>, f: impl Fn( T) -> U) -> Vec<U> {...}
0 голосов
/ 12 октября 2019

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

Используя только изменяемые ссылки, вы не можете быть в этом уверены, поэтому вам нужно сделать полные копии. Копирование данных занимает время и пространство, которые всегда ограничены. Главный вопрос для производительности, как правило, заключается в том, помещаются ли ваши данные в кэш процессора.

Я предполагаю, что вы думали о типах «копирования» как о тех, которые помещаются в то же пространство, что и сама ссылка, то есть sizeof(type) <= sizeof(type*). Черта Rust Copy указывает на данные, которые можно безопасно копировать, независимо от размера. Это ортогональные понятия;например, указатель может быть не скопирован безопасно без настройки количества ссылок, или массив может быть скопирован, но занимает гигабайты памяти. Вот почему Rc<T> имеет черту Клона, а не Копировать.

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