标签: borrowing

为什么不鼓励接受对String(&String),Vec(&Vec)或Box(&Box)的引用作为函数参数?

我写了一些Rust代码&String作为参数:

fn awesome_greeting(name: &String) {
    println!("Wow, you are awesome, {}!", name);
}
Run Code Online (Sandbox Code Playgroud)

我还编写了代码来引用a VecBox:

fn total_price(prices: &Vec<i32>) -> i32 {
    prices.iter().sum()
}

fn is_even(value: &Box<i32>) -> bool {
    **value % 2 == 0
}
Run Code Online (Sandbox Code Playgroud)

但是,我收到一些反馈意见,这样做并不是一个好主意.为什么不?

string reference rust borrowing

100
推荐指数
2
解决办法
5549
查看次数

如何决定函数输入参数何时应为引用?

在编写函数时,如何决定是引用还是使用输入参数?

例如,我应该这样做吗?

fn foo(val: Bar) -> bool { check(val) } // version 1
Run Code Online (Sandbox Code Playgroud)

或者使用引用参数代替?

fn foo(val: &Bar) -> bool { check(*val) } // version 2
Run Code Online (Sandbox Code Playgroud)

在客户端,如果我只有第二个版本但想要消耗我的价值,我必须这样做:

// given in: Bar
let out = foo(&in); // using version 2 but wanting to consume ownership
drop(in);
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我只有第一个版本但想保留我的参考,我必须这样做:

// given in: &Bar
let out = foo(in.clone()); // using version 1 but wanting to keep reference alive
Run Code Online (Sandbox Code Playgroud)

那么哪个是首选,为什么?

做出此选择时是否有任何性能考虑?或者编译器是否使它们在性能方面等效,以及如何实现?

您什么时候想提供两个版本(通过特征)?在那些时候,您如何编写这两个函数的底层实现——您是否复制每个方法签名中的逻辑,或者您是否有一个代理到另一个函数?哪个到哪个,为什么?

ownership rust borrowing

20
推荐指数
2
解决办法
5038
查看次数

在迭代递归结构时无法获得可变引用:不能一次多次借用可变引用

我试图迭代地导航递归数据结构,以便在某个位置插入元素.根据我的有限理解,这意味着对结构的根进行可变引用,并通过对其跟随者的引用连续替换它:

type Link = Option<Box<Node>>;

struct Node {
    next: Link
}

struct Recursive {
    root: Link
}

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;
        while let Some(ref mut node) = *anchor {
            anchor = &mut node.next;
        }
        anchor
    }
}
Run Code Online (Sandbox Code Playgroud)

(Rust操场链接)

但是,这失败了:

error[E0499]: cannot borrow `anchor.0` as mutable more than once at a time
  --> src/main.rs:14:24
   |
14 |         while let Some(ref mut node) = *anchor {
   |                        ^^^^^^^^^^^^
   |                        | …
Run Code Online (Sandbox Code Playgroud)

mutable rust borrowing

16
推荐指数
3
解决办法
2405
查看次数

无法推断返回引用的闭包的适当生命周期

考虑以下代码:

fn foo<'a, T: 'a>(t: T) -> Box<Fn() -> &'a T + 'a> {
    Box::new(move || &t)
}
Run Code Online (Sandbox Code Playgroud)

我期待的是:

  • T型具有寿命'a.
  • 这个价值t只要有效T.
  • t 移动到关闭,所以关闭生活只要 t
  • 闭包返回一个引用t移动到闭包的引用.因此只要闭包存在,引用就是有效的.
  • 没有生命周期问题,代码编译.

实际发生了什么:

  • 代码无法编译:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
 --> src/lib.rs:2:22
  |
2 |     Box::new(move || &t)
  |                      ^^
  |
note: first, the lifetime cannot outlive the lifetime  as defined on the body at 2:14...
 --> src/lib.rs:2:14
  |
2 | …
Run Code Online (Sandbox Code Playgroud)

closures ownership rust borrowing

16
推荐指数
2
解决办法
967
查看次数

在Rust中取消引用字符串和HashMaps

我试图理解HashMaps在Rust中是如何工作的,我已经提出了这个例子.

use std::collections::HashMap;

fn main() {
    let mut roman2number: HashMap<&'static str, i32> = HashMap::new();
    roman2number.insert("X", 10);
    roman2number.insert("I", 1);

    let roman_num = "XXI".to_string();
    let r0 = roman_num.chars().take(1).collect::<String>();
    let r1: &str = &r0.to_string();
    println!("{:?}", roman2number.get(r1)); // This works

    // println!("{:?}", roman2number.get(&r0.to_string())); // This doesn't
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译最后一行未注释的代码时,我收到以下错误

error: the trait bound `&str: std::borrow::Borrow<std::string::String>` is not satisfied [E0277]
println!("{:?}", roman2number.get(&r0.to_string()));
                                            ^~~
note: in this expansion of format_args!
note: in this expansion of print! (defined in <std macros>)
note: in this expansion of println! (defined …
Run Code Online (Sandbox Code Playgroud)

hashmap dereference rust borrowing

14
推荐指数
2
解决办法
3267
查看次数

价值不够长

我不完全了解生命,但我认为b生命将在此之前结束self.

那么,如何编辑这段代码呢?我在内存中复制一些东西吗?如果我创建一个新实例,这个生命周期必须遵循这种情况.

pub struct Formater {
    layout: &'static str,
}

impl Formater {
    pub fn new(layout: &'static str) -> Formater {
        let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
        let b = regex.replace_all(layout, "{}");

        return Formater {
            layout: &b,
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

错误:

error: `b` does not live long enough
  --> src/format.rs:16:22
   |
16 |             layout: &b,
   |                      ^ does not live long enough
17 |         };
18 |     }
   |     - borrowed value only lives until here
   |
   = …
Run Code Online (Sandbox Code Playgroud)

lifetime rust borrowing

10
推荐指数
1
解决办法
7149
查看次数

当返回对范围之外的值的可变引用的不可变引用时,为什么在范围结束时删除了可变引用?

fn main() {
    // block1: fails
    {
        let mut m = 10;

        let n = {
            let b = &&mut m;
            &**b // just returning b fails
        };

        println!("{:?}", n);
    }

    // block2: passes
    {
        let mut m = 10;

        let n = {
            let b = &&m;
            &**b // just returning b fails here too
        };

        println!("{:?}", n);
    }
}
Run Code Online (Sandbox Code Playgroud)

block1因错误失败:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:7:22
   |
7  |             let b …
Run Code Online (Sandbox Code Playgroud)

mutable dereference rust borrowing

10
推荐指数
1
解决办法
248
查看次数

Rust的借用规则是否妨碍了功能数据结构的发展?

功能数据结构(例如Haskell/Clojure/Scala中使用的Hash Array Mapped Trie)依赖于底层数据结构中的大量共享.例如,如果我们实现insert类似于地图的数据类型,通常通过在实现数据结构的树上进行路径复制来实现.

鉴于这些数据结构在很大程度上依赖于基础价值的共享(并且没有主要所有者),借款是否会妨碍实施此类结构?

rust borrowing

9
推荐指数
1
解决办法
968
查看次数

为什么在这里使用"&&"?

在这里有两个问题.

let a = [1, 2, 3];

assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
assert_eq!(a.iter().find(|&&x| x == 5), None);
Run Code Online (Sandbox Code Playgroud)

1.为什么&&x在闭包参数中使用而不仅仅是x?(我理解"&"正在传递一个对象的引用,但是两次使用它的意思是什么?)

这本书写道:

因为find()接受引用,并且许多迭代器遍历引用,这导致可能令人困惑的情况,其中参数是双引用.您可以在下面的示例中看到此效果,使用&& x.

但我真的不明白.

2.为什么&用而不是find()

reference rust borrowing

9
推荐指数
1
解决办法
576
查看次数

在什么情况下,不借用的API更受欢迎?

Rust拥有所有权和借贷的概念.如果函数没有将其参数作为引用借用,则该函数的参数将被移动,并且一旦超出范围将被释放.

采取这个功能:

fn build_user(email: String, username: String) -> User {
    User {
        email: email,
        username: username,
    }
}
Run Code Online (Sandbox Code Playgroud)

此功能可以称为:

let email = String::from("foo@example.com");
let username = String::from("username");

let user = build_user(email, username);
Run Code Online (Sandbox Code Playgroud)

由于emailusername已被移动,他们不能再被使用之后build_user被调用.

这可以通过使API使用借来的引用来修复.

考虑到这一点,在设计API时,哪些场景总是倾向于不使用借用?

api-design reference move-semantics rust borrowing

9
推荐指数
1
解决办法
411
查看次数