Я хочу создать простой пример для проверки перемещения объекта в памяти и выяснить, меняется ли адрес объекта, когда он передается от одного владельца к другому. Я предполагаю, что адрес не должен меняться, так как речь идет о перемещении, которое существует только в исходном коде для ссылочных типов. Эти типы выделяют память в куче, и переменная ссылается на объект. Я об этом иду разговор, когда упоминаю тип `Box`. Я ожидаю, что после перемещения данные будут по тому же адресу, поскольку если Rust будет копировать данные в куче, это будет неэффективно и не оптимально. Однако я не могу написать пример, чтобы он скомпилировался, без вызова метода `clone()`. <br/> <pre><code>#![allow(unused)] fn main() { let b = Box::new(4); check_b(&b); let c = b; // Здесь происходит move check_c(&c); } fn check_c(val: &Box<i32>){ println!("address c: {}\n", Box::into_raw(val.clone()) as usize); } fn check_b(val: &Box<i32>){ println!("address b: {}\n", Box::into_raw(val.clone()) as usize); }</code></pre> <br/> В результате вызова `clone()` я не могу это проверить, поскольку данные копируются: <br/> <br/> address b: 104808743070512 <br/> <br/> address c: 104808743070544 <br/> <br/> Как мне переписать пример, чтобы проверить изменение адреса объекта? <br/> Спасибо.
В вашем примере проблема в том, что при вызове метода `clone()` вы создаете новую копию объекта, и результатом является новый адрес в памяти. Чтобы проверить, изменяется ли адрес объекта при перемещении, вам нужно обойтись без клонирования. Вот как можно переписать ваш код так, чтобы он корректно показывал адреса объекта до и после перемещения: ```rust #![allow(unused)] fn main() { let b = Box::new(4); check_b(&b); let c = b; // Здесь происходит перемещение check_c(&c); } fn check_c(val: &Box<i32>) { println!("address c: {}\n", Box::into_raw(val) as usize); } fn check_b(val: &Box<i32>) { println!("address b: {}\n", Box::into_raw(val) as usize); } ``` Тем не менее, чтобы перемещение прошло успешно, вам нужно изменить функцию `check_c` так, чтобы она принимала `Box<i32>` вместо ссылки, потому что при перемещении вдали от `b` у вас не будет доступа к оригиналу. Таким образом, мы можем выполнить следующий код: ```rust #![allow(unused)] fn main() { let b = Box::new(4); let b_address = Box::into_raw(b); // Получаем адрес до перемещения println!("address b: {}\n", b_address as usize); let c = unsafe { Box::from_raw(b_address) }; // Здесь происходит перемещение let c_address = Box::into_raw(c); // Получаем адрес после перемещения println!("address c: {}\n", c_address as usize); } ``` В этом коде: 1. Мы используем `Box::into_raw` для получения адреса объекта в куче. 2. Присваиваем значение `b` переменной `c`. Обратите внимание, что для этого мы используем `unsafe`, чтобы создать `Box` из адреса. 3. После этого, когда мы снова получаем адрес с помощью `Box::into_raw`, вы сможете увидеть, что адрес не изменился. Важно учитывать, что с использованием `unsafe` вы берете на себя ответственность за безопасное управление памятью, поэтому необходимо внимательно относиться к тому, как вы используете выделенную память.
Я изменил пример и получилось, что походу адрес не меняется. То есть при перемещении владения объект лежит там же в памяти:
#![allow(unused)] fn main() { let b = Box::new(4); check_b(&b); let c = b; // Здесь происходит move check_c(&c); } fn check_c(val: &Box<i32>){ println!("address c: {}\n", &raw const val as usize); } fn check_b(val: &Box<i32>){ println!("address b: {}\n", &raw const val as usize); }
address b: 140733161839864
address c: 140733161839864
Как проверить перемещается ли в памяти объект при «перемещении»?
В общем случае: посмотреть реализован ли Copy, поскольку у него семантика перемещения заменяется на семантику копирования. За исключением Copy все копирования и аллокации в расте явные, вроде методов clone() или to_vec().
В случае с Box вы уже сами пришли к ответу, достаточно было просмотреть на адрес в указателе.
Ну и код проверки какой-то странный, достаточно этого
fn main() { let b = Box::new(4); check(&b); let c = b; check(&c); } fn check(val: &i32) { println!("address: {:p}", val); }