如何在 Rust 中操作可变结构的实例 - 所有权问题

问题描述 投票:0回答:2

我刚刚学习 Rust,已经学习了多年的 C++,并且在理解如何处理一些所有权限制方面遇到了一些困难。具体来说,在这个只是训练练习的小程序中,我收到两个不同的错误消息。

let stat = Stdev::new();

上面的语句得到消息:发生移动是因为

stat
的类型为
Stdev
,它没有实现
Copy
特征

    stat.add(x);

上面的语句获取消息:

stat
由于此方法调用而移动,在循环的上一次迭代中。

以下是整个程序:

struct Stdev
{
    count : u32,
    sum : f64,
    sq_sum : f64
}

impl Stdev
{
    fn new() -> Self
    {
        Stdev{count:0, sum:0.0, sq_sum:0.0}
    }

    fn add(mut self, x : f64)
    {
        self.count += 1;
        self.sum += x;
        self.sq_sum += x * x;
    }
    
    fn stdev(&self) -> f64
    {
        if self.count == 0 { return 0.0; }
        let n = self.count as f64;
        let mean = self.sum / n;
        let variance = self.sq_sum / n - mean * mean;
        variance.sqrt()
    }
}

use rand::Rng;

fn main() {
    let count = 1000;
    let stat = Stdev::new();
    for _ in 1..count
    {
        let x = rng.gen_range(0.0..100.0);
        stat.add(x);
    }
    
    println!("Standard deviation is {}", stat.stdev());
}



所以,有两个问题:
1:如何使用

stat
结构体的实例初始化变量
Stdev

2:如何通过方法调用修改结构体中的字段,而不会遇到所有权问题?

作为参考,这里的逻辑本质上是相同的,用 C++ 而不是 Rust,并且这个程序运行得很好。在以下代码中,类

accum
相当于 Rust 结构体
Stdev

#include <iostream>
#include <cmath>

class accum
{
    int count;
    double sum;
    double sq_sum;
    
public:
    accum();
    int add(double);
    double stdev();
};

accum::accum()
{
    count = 0;
    sum = 0.0;
    sq_sum = 0.0;
}

int accum::add(double x)
{
    sum += x;
    sq_sum += x * x;
    return ++count;
}

double accum::stdev()
{
    if (0 == count) return 0;
    double mean = sum / count;
    double variance = sq_sum / count - mean * mean;
    return sqrt(variance);
}

double gen_range()
{
    double x = rand();
    x /= RAND_MAX;
    return x * 100.0;
}

int main()
{
    int count = 100;
    accum stat;
    for(int i = 0; count > i; ++i)
    {
        double x = gen_range();
        stat.add(x);
    }
    
    std::cout << "Standard deviation is " << stat.stdev() << "\n";
}

我对第二个错误特别困惑。如果

stat
被移动,它被移动到哪里?没有赋值,只有方法调用。我很困惑。谢谢。

rust
2个回答
1
投票

更改

add
函数以获取对
self
的可变引用,而不是移动它:

fn add(&mut self, x: f64)

使用当前声明,调用

add
实际上会移动
stat
并将所有权传递给
add
方法。因此,在该调用之后无法使用
stat
,但循环需要它,这就是您收到错误的原因。

你的

new
方法很好。


0
投票
struct Stdev {
    count: u32,
    sum: f64,
    sq_sum: f64,
}

impl Stdev {
    fn new() -> Self {
        Stdev {
            count: 0,
            sum: 0.0,
            sq_sum: 0.0,
        }
    }

    fn add(&mut self, x: f64) {
        self.count += 1;
        self.sum += x;
        self.sq_sum += x * x;
    }

    fn stdev(&self) -> f64 {
        if self.count == 0 {
            return 0.0;
        }
        let n = self.count as f64;
        let mean = self.sum / n;
        let variance = self.sq_sum / n - mean * mean;
        variance.sqrt()
    }
}

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    let count = 1000;
    let mut stat = Stdev::new();
    for _ in 1..count {
        let x = rng.gen_range(0.0..100.0);
        stat.add(x);
    }

    println!("Standard deviation is {}", stat.stdev());
}

  • 结果
Standard deviation is 29.224928446158625
© www.soinside.com 2019 - 2024. All rights reserved.