rust tech trash是什么_rust入门笔记---函数实现引用传递

引出问题

在学习所有权时,我从网上发现了这段代码:

fn overwrite(dest: &mut T, original: &T) {

*dest = *original;

}

这段代码是用一个共享引用的值去覆盖一个可变引用的值。这里因*操作有move值的要求,所以T必须实现copy,如果original类型简单,拷贝一次也无所谓,那如果original又大又复杂呢?这里把original的共享引用传给dest不是更高效?

身体力行

当然上面代码简单的把签名里的: Copy给去掉肯定不行,那如何实现呢?虽然我觉得我上面的想法理论上可行,但还是先验证一下:

use std::ptr;

let a = "a".to_string();

let mut b = &("b".to_string());

b = &a;

// overwrite_with_no_copy(b, &a);

assert!(ptr::eq(&a, b));

那我就信心满满的写下overwrite_with_no_copy这个版本:

use std::ptr;

fn overwrite_with_no_copy(output: &'a mut String, input: &'a String) {

output = input;

}

fn main() {

let a = "a".to_string();

let mut b = &("b".to_string());

overwrite_with_no_copy(b, &a);

assert!(ptr::eq(&a, b));

}

但这里报错:

error[E0308]: mismatched types

--> src\main.rs:3:14

|

3 | output = input;

| ^^^^^ types differ in mutability

|

= note: expected mutable reference `&'a mut std::string::String`

found reference `&'a std::string::String`

上面提示其实挺清楚了,但我当时就是参不透。所以我又群上求助,但因为我表达能力有限,大家始终不明白我的“初心”。好在群里的大佬“@沙渺”他一眼就猜中了我的意图,给我了如下版本:

fn overwrite_with_no_copy(output: &mut &'a String, input: &'a String) {

*output = input;

}

fn main() {

use std::ptr;

let b = "b".to_string();

let mut c = &("trash".to_string());

overwrite_with_no_copy(&mut c, &b);

println!("ptr(B):{:p}, ptr(*C):{:p}", &b, &*c);

assert!(ptr::eq(&*c, &b));

}

原来我离正解如此之近了,是我之前纠结在如何把&T传给&mut T,原来需要把&T传给&mut &T,再次感谢@沙渺!

这里我还从大佬的代码里学习到原来println!的格式输出还能打印内存地址,于是顺藤摸瓜,我又复习了一遍std::fmt,其中重点我拿小本本摘录如下: When requesting that an argument be formatted with a particular type, you are actually requesting that an argument ascribes to a particular trait. This allows multiple actual types to be formatted via {:x} (like i8 as well as isize). The current mapping of types to traits is:nothing ⇒ Display

? ⇒ Debug

x? ⇒ Debug with lower-case hexadecimal integers

X? ⇒ Debug with upper-case hexadecimal integers

o ⇒ Octal

x ⇒ LowerHex

X ⇒ UpperHex

p ⇒ Pointer

b ⇒ Binary

e ⇒ LowerExp

E ⇒ UpperExp

What this means is that any type of argument which implements the fmt::Binary trait can then be formatted with {:b}. Implementations are provided for these traits for a number of primitive types by the standard library as well. If no format is specified (as in {} or {:6}), then the format trait used is the Display trait.

继续深挖

人家原来是泛型,那改成了泛型试试,试试也能通过:

fn overwrite_with_no_copy(output: &mut &'a T, input: &'a T) {

*output = input;

}

后来觉得'a, T这样还是有些啰嗦,进一步简化:

fn overwrite_with_no_copy(output: &mut U, input: U) {

*output = input;

}

也能编译通过。看来适当的抽象还能隐藏掉烦人的生命周期!

事后我仍觉得这里的U应该被限制一下,忽然我灵光一现:我经常看到貌似无用的生命周期表达,会不会用处就在这里,于是我进一步改进:

fn overwrite_with_no_copy(output: &mut U, input: U) {

*output = input;

}

至此,虽然我还不能明确解释这种表达方式,但我觉得我这次get到了Rust的真谛。

总结

“回”字的写法有四种,并且一种比一种优雅深邃....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值