Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/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 - Fatal编程技术网

Rust 为什么我必须声明一个变量为可变的,以便内部函数修改它自己的内容?

Rust 为什么我必须声明一个变量为可变的,以便内部函数修改它自己的内容?,rust,Rust,我有一个CPUstruct和load\u rom方法: use std::fs::File; use std::io::{self, Read}; pub struct CPU { pub mem: [u8; 4096], V: [u8; 16], I: u16, stack: [u16; 16], opcode: u16, } impl CPU { pub fn new() -> CPU { CPU {

我有一个
CPU
struct和
load\u rom
方法:

use std::fs::File;
use std::io::{self, Read};

pub struct CPU {
    pub mem: [u8; 4096],
    V: [u8; 16],
    I: u16,
    stack: [u16; 16],
    opcode: u16,
}

impl CPU {
    pub fn new() -> CPU {
        CPU {
            mem: [0; 4096],
            V: [0; 16],
            I: 0,
            stack: [0; 16],
            opcode: 0,
        }
    }
    pub fn load_rom(&self, filepath: &str) {
        let mut rom: Vec<u8> = Vec::new();
        let mut file = File::open(filepath).unwrap();
        file.read_to_end(&mut rom);

        for (i, mut byte) in rom.iter().enumerate() {
            self.mem[i] = *byte;
        }
    }
}

fn main() {}
当我用
创建一个CPU时,让mut CPU=CPU::new()
并将
&mut self
传递到
load\u rom
方法,一切正常

如果在创建时未使用
mut
,则会出现以下错误:

错误:无法将不可变的局部变量'cpu'借用为可变的
-->src/main.rs:10:2
|
9 |让cpu=cpu::new();
|---在这里使用'mut cpu'使可变
10 | cpu.load_rom(“/Users/../Code/Rust/chip8/src/roms/connect4.ch8”);
|^^^不能相互借用

为了让内部函数修改自己的内容,我必须使
cpu
可变,这似乎是不对的。我真的必须声明
cpu
是可变的吗?还是我遗漏了什么?

Rust使用了一个可传递的不变性模型。这意味着,如果一个变量被标记为
不可变
,则该变量可能不会发生突变,并且通过该变量访问的数据可能不会发生突变

此外,如果您有一个变量的可变引用,则类型系统不允许任何不可变的引用共存;所以,并没有标记为“mut”的数据在不可变引用的整个生命周期中都是不变的

这使得默认情况下,不可能同时有两个对同一数据的可变引用。这是高效内存安全和线程安全的要求;同时也使得对锈迹代码中的变异进行推理变得更加简单

如果需要“内部”可变性,可以使用
std::Cell
模块中的
Cell
RefCell
。然而,对于一个CPU结构来说,这样做可能是错误的,因为它表示一个预期要运行的CPU,并且在每次操作后其状态都会改变。内部可变性通常应保留用于在不执行对象的任何逻辑(外部可见)突变的操作的实现中执行突变。CPU运行操作或加载内存不是很好的选择,因为诸如“加载内存”、“运行指令”之类的每个操作都会改变CPU的逻辑状态


有关何时可能需要内部可变性的进一步讨论,请参阅。

Rust使用可传递的不变性模型。这意味着,如果一个变量被标记为
不可变
,则该变量可能不会发生突变,并且通过该变量访问的数据可能不会发生突变

此外,如果您有一个变量的可变引用,则类型系统不允许任何不可变的引用共存;所以,并没有标记为“mut”的数据在不可变引用的整个生命周期中都是不变的

这使得默认情况下,不可能同时有两个对同一数据的可变引用。这是高效内存安全和线程安全的要求;同时也使得对锈迹代码中的变异进行推理变得更加简单

如果需要“内部”可变性,可以使用
std::Cell
模块中的
Cell
RefCell
。然而,对于一个CPU结构来说,这样做可能是错误的,因为它表示一个预期要运行的CPU,并且在每次操作后其状态都会改变。内部可变性通常应保留用于在不执行对象的任何逻辑(外部可见)突变的操作的实现中执行突变。CPU运行操作或加载内存不是很好的选择,因为诸如“加载内存”、“运行指令”之类的每个操作都会改变CPU的逻辑状态

有关何时可能需要内部可变性的进一步讨论,请参阅

使
cpu
可变,以便内部函数修改其自身内容

(强调矿山)

Rust是一种系统语言,这意味着它试图让您能够创建快速高效的代码。实现这一点的主要方法之一是提供对现有数据的引用,而不是复制现有数据

Rust也是一种安全的语言,这意味着(除其他外)不可能访问无效的引用

为了实现这两个目标,必须进行权衡。一些语言将安全检查转移到运行时,强制执行强制同步原语(例如互斥和好友),或其他一些有趣的解决方案。一些语言完全避免了混乱,选择不允许引用或不试图保证安全

Rust与这些不同之处在于,它在编译时检查尽可能多的内容。这意味着编译器必须能够推断内存块何时何地可能发生变异

如果它不知道这一点,那么您可能会获取对某个值中某个内容的引用,然后对该值调用一个使引用无效的变异方法。当您使用现在无效的引用时BOOOOM。你的程序在最好的情况下崩溃,或者泄露信息,或者在最坏的情况下创建后门

&mut self
向编译器指示此方法可能会改变其中的值。只有在变量绑定上(
mut-cpu
此处)的
mut
关键字表示的值已经是可变的,才能获取对该值的可变引用

然而,这不仅仅对编译器有用。知道某些东西正在被改变对程序员来说也是非常有价值的。在一个大系统中,易变性增加了复杂性的难以解释性,当某些东西是和不是易变的时候,被迫显式地列出这些东西可以提供非常丰富的信息,并且在精神上也很自由

了解生锈的原因也很有用。
* one or more references (`&T`) to a resource,
* exactly one mutable reference (`&mut T`).
pub fn load_rom(&mut self, filepath: &str) {
    let mut file = File::open(filepath).unwrap();
    file.read_exact(&mut self.mem);
}