Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 使用可变引用覆盖变量时发生借用检查器错误_Rust_Borrow Checker - Fatal编程技术网

Rust 使用可变引用覆盖变量时发生借用检查器错误

Rust 使用可变引用覆盖变量时发生借用检查器错误,rust,borrow-checker,Rust,Borrow Checker,我有一个structUI包含对Stdout的可变引用。我宁愿用一个全新的UI: 使用std::io::{stdout,Result,stdout,Write}; 结构用户界面{ fn新(标准输出:和的多标准输出)->结果{ 让ui=ui{ stdout:stdout, v:Box::新(()), }; Ok(用户界面) } fn写入(&mut self)->结果{ 写!(self.stdout,“heyyyy”)?; self.stdout.flush()?; 好(()) } } fn main

我有一个struct
UI
包含对
Stdout
的可变引用。我宁愿用一个全新的
UI
:

使用std::io::{stdout,Result,stdout,Write};
结构用户界面{
fn新(标准输出:和的多标准输出)->结果{
让ui=ui{
stdout:stdout,
v:Box::新(()),
};
Ok(用户界面)
}
fn写入(&mut self)->结果{
写!(self.stdout,“heyyyy”)?;
self.stdout.flush()?;
好(())
}
}
fn main()->结果{
设mut stdout=stdout();
让mut ui=ui::new(&mut stdout)?;
ui=ui::新建(&mut stdout)?;
ui.write()?;//如果注释掉这一行,错误就会消失。
好(())
}

借用检查器抱怨标准输出被可变借用两次:

error[E0499]:不能一次多次将'stdout'作为可变项借用
-->src/main.rs:30:18
|
28 |让mut ui=ui::new(&mut stdout)?;
|--------第一个可变借用发生在此处
29 | 
30 | ui=ui::新建(&mut stdout)?;
|-->^^^^^^^^^^^第二个可变借用发生在此处
|     |
|当删除'ui'并运行'ui Result'类型的析构函数时,这里可以使用first-borrow{
设mut stdout=stdout();
让mut ui=ui::new(&mut stdout)?;
对于0..10中的uu{
下降(ui);
ui=ui::新建(&mut stdout)?;
ui.write()?;
}
好(())
}
error[E0499]:不能一次多次将'stdout'作为可变项借用
-->src/main.rs:33:22
|
28 |让mut ui=ui::new(&mut stdout)?;
|--------第一个可变借用发生在此处
...
33 | ui=ui::新建(&mut stdout)?;
|-->^^^^^^^^^^^第二个可变借用发生在此处
|         |

|这里可以使用first borrow,当删除'ui'并在替换值时运行'ui类型的析构函数时,必须首先创建新值:

struct Noisy(u8);

impl Noisy {
    fn new(v: u8) -> Self {
        eprintln!("creating {}", v);
        Self(v)
    }
}

impl Drop for Noisy {
    fn drop(&mut self) {
        eprintln!("dropping {}", self.0);
    }
}

fn main() {
    let mut ui = Noisy::new(1);
    ui = Noisy::new(2);
}
创建1
创建2
下降1
下降2
这意味着您的两个
UI
结构将尝试共存。由于它们都有一个对stdout的可变引用
Drop::Drop
实现可能会变异
stdout
,这将违反引用规则,因为在一个点上会有多个活动的可变引用

当您不调用
write
时,非词汇借用检查器会发现不需要借用,因此没有问题

那么为什么[在重新分配之前显式删除该值]会返回错误

因为那是

另见:


错误消息中解释了第一点,但如果您不知道发生了什么,则会以迂回的方式解释<代码>框实现
删除
,以便在销毁时可以解除分配其内容;因此,
UI
会自动执行
Drop
,这意味着在为新的
UI
重新加载它和将它分配给
UI
之间,执行的代码可以访问
stdout
,可能是编译器意识到没有使用
ui
,因此实际上没有执行赋值,但这只是一个猜测。
take()
是一个很好的解决方案,但是请注意,该方法的一个更惯用的名称是
into\u stdout()
-在将
锈蚀为
的过程中,方法消耗
自我
,并返回对象曾经拥有的内部事物的所有权。在这种情况下,您将返回原始的
&mut stdout
(具有原始生存期),这允许您创建与原始用户“兼容”的新
ui