我刚刚学习 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
?作为参考,这里的逻辑本质上是相同的,用 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
被移动,它被移动到哪里?没有赋值,只有方法调用。我很困惑。谢谢。
更改
add
函数以获取对 self
的可变引用,而不是移动它:
fn add(&mut self, x: f64)
使用当前声明,调用
add
实际上会移动 stat
并将所有权传递给 add
方法。因此,在该调用之后无法使用 stat
,但循环需要它,这就是您收到错误的原因。
你的
new
方法很好。
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