reference - 用于处理对缓冲区的引用的惯用 Rust 方法

标签 reference rust

我希望能够构造包含对可变缓冲区对象的不可变引用的对象。以下代码不起作用,但说明了我的用例,是否有惯用的 Rust 方法来处理这个问题?

#[derive(Debug)]
struct Parser<'a> {
    buffer: &'a String
}

fn main() {
    let mut source = String::from("Peter");
    let buffer = &source;
    let parser = Parser { buffer };

    // How can I legally change source?
    source.push_str(" Pan");

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

最佳答案

rust borrow checker 的黄金法则是:一次只有一个写入者或多个读取者可以访问一个资源。这确保了算法可以安全地在多线程中运行。

你在这里违反了这条规则:

#[derive(Debug)]
struct Parser<'a> {
    buffer: &'a String
}

fn main() {
    // mutable access begins here
    let mut source = String::from("Peter");
    // immutable access begins here
    let buffer = &source;
    let parser = Parser { buffer };

    source.push_str(" Pan");

    println!("{:?}", parser);
    // Both immutable and mutable access end here
}

如果您确定您的程序不会同时以可变和不可变方式主动访问资源,您可以通过将资源包装在 RefCell 中,将检查从编译时转移到运行时:

use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
struct Parser {
    buffer: Rc<RefCell<String>>
}

fn main() {
    let source = Rc::new(RefCell::new(String::from("Peter")));
    let parser = Parser { buffer: source.clone() };

    source.borrow_mut().push_str(" Pan");

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

如果你计划在线程周围传递你的资源,你可以使用 RwLock 来阻塞线程直到资源可用:

use std::sync::{RwLock, Arc};

#[derive(Debug)]
struct Parser {
    buffer: Arc<RwLock<String>>
}

fn main() {
    let source = Arc::new(RwLock::new(String::from("Peter")));
    let parser = Parser { buffer: source.clone() };

    source.write().unwrap().push_str(" Pan");

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

另一方面,您应该更喜欢 &str 而不是 &String

关于reference - 用于处理对缓冲区的引用的惯用 Rust 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45796365/

相关文章:

rust - 在 Rust 中使用不同的字符串类型和 if else 结构

rust - 我应该使用 libc::c_char 还是 std::os::raw::c_char?

c++ - const 非引用参数

用于唯一对象实例的 Java Map?

C++ 运算符重载和析构函数

reference - 词法作用域和共享对象

rust - 如何包装对在 Rust 中使用 VarArgs 的 FFI 函数的调用?

rust/柴油 : How to query and insert into postgres tables which have uuid

random - 是否可以使用任意长度的向量作为种子来创建RNG,而无需自己创建完整的RNG实现?

c++ - 模板转发对成员方法的调用