rust 如何在不使用clone()或copy()的情况下修复此引用相关错误?[已关闭]

xe55xuns  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(122)

已关闭,此问题需要更focused,目前不接受回答。
**要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

2天前关闭。
Improve this question
请查看以下两个函数和错误信息。
是否可以在不使用clone()copy()函数的情况下修复这两个函数?
另外,你能回答评论中的问题吗?

pub fn Vec3::transform(vector: Vec3, matrix: Matrix3x3) -> Vec3
    {
        return Vec3 
        {
            integer: vector.integer * matrix.integer,
            double: vector.double * matrix.double,
            string: vector.string + &matrix.string,//why is "&" needed here as we are not modifying matrix.string? 
        }
    }
pub fn Rototranslation::apply_mut(&self, vector: &Vec3) -> Vec3 //why is not a "mut" needed here?
    {
        let transformed_vector = *vector - self.origin_vector;//why do we need a dereference here?
        let temp_matrix = &self.rotation_matrix; 
        let transformed_vector = Vec3::transform(transformed_vector, temp_matrix);
        return transformed_vector + self.origin_vector;
    }

输出

Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
   --> src/main.rs:141:70
    |
141 |         let transformed_vector = Vec3::transform(transformed_vector, &mut temp_matrix);
    |                                  ---------------                     ^^^^^^^^^^^^^^^^ expected struct `Matrix3x3`, found `&mut &Matrix3x3`
    |                                  |
    |                                  arguments to this function are incorrect
    |
note: associated function defined here
   --> src/main.rs:49:12
    |
49  |     pub fn transform(vector: Vec3, matrix: Matrix3x3) -> Vec3 // a fake operation
    |            ^^^^^^^^^               -----------------

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

完整源代码

use std::ops::{Add, Sub};

struct Vec3 
{
    pub integer: i32,
    pub double: f64,
    pub string: String,
}

impl Add<Vec3> for Vec3 //overloaded binary addition operator for Vec3 
{
    type Output = Vec3;
    fn add(self, other: Vec3) -> Vec3 
    {
        Vec3 
        {
            integer: self.integer + other.integer,
            double: self.double + other.double,
            string: self.string + &other.string,
        }
    }
}

impl Sub<Vec3> for Vec3 //overloaded binary subtraction operator for Vec3 
{
    type Output = Vec3;
    fn sub(self, other: Vec3) -> Vec3 
    {
        Vec3 
        {
            integer: self.integer - other.integer,
            double: self.double - other.double,
            string: self.string.replace(&other.string, ""),
        }
    }
}

impl Vec3 
{
    pub fn new(integer: i32, double: f64, string: String) -> Vec3
    {
        return Vec3 //constructing and returning a Vec3 object 
        {
            integer,
            double,
            string,
        }
    }
    pub fn transform(vector: Vec3, matrix: Matrix3x3) -> Vec3 // a fake operation
    {
        return Vec3 
        {
            integer: vector.integer * matrix.integer,
            double: vector.double * matrix.double,
            string: vector.string + &matrix.string,
        }
    }
    pub fn print(&self)
    {
        print!("{} ", self.integer);
        print!("{} ", self.double);
        print!("{} \n", self.string);
    }
}

struct Matrix3x3 // A fake Matrix type
{
    pub integer: i32,
    pub double: f64,
    pub string: String,
}

impl Add<Matrix3x3> for Matrix3x3 //overloaded binary addition operator for Matrix3x3 
{
    type Output = Matrix3x3;
    fn add(self, other: Matrix3x3) -> Matrix3x3 
    {
        Matrix3x3 
        {
            integer: self.integer + other.integer,
            double: self.double + other.double,
            string: self.string + &other.string,
        }
    }
}

impl Sub<Matrix3x3> for Matrix3x3 //overloaded binary subtraction operator for Matrix3x3 
{
    type Output = Matrix3x3;
    fn sub(self, other: Matrix3x3) -> Matrix3x3 
    {
        return Matrix3x3 
        {
            integer: self.integer - other.integer,
            double: self.double - other.double,
            string: self.string.replace(&other.string, ""),
        }
    }
}

impl Matrix3x3 
{
    pub fn new(integer: i32, double: f64, string: String) -> Matrix3x3 
    {
        return Matrix3x3 //constructs a Matrix3x3 object and returns it
        {
            integer,
            double,
            string,
        }
    }
    pub fn print(&self)
    {
        print!("{} ", self.integer);
        print!("{} ", self.double);
        print!("{} \n", self.string);
    }
}

struct Rototranslation
{
    pub origin_vector: Vec3,
    pub rotation_matrix: Matrix3x3,
}

impl Rototranslation 
{
    pub fn new(my_vec: Vec3, mat: Matrix3x3) -> Rototranslation 
    {
        return Rototranslation
        {
            origin_vector: my_vec,
            rotation_matrix: mat,
        }
    }    
    
    // A fake operation
    pub fn apply_mut(&self, vector: &Vec3) -> Vec3 
    {
        let transformed_vector = *vector - self.origin_vector;
        let temp_matrix = &self.rotation_matrix; // "&" needed here coz we are not using copy or clone
        let transformed_vector = Vec3::transform(transformed_vector, temp_matrix);
        return transformed_vector + self.origin_vector;
    }    
    fn print(&self)
    {
        self.origin_vector.print();
        self.rotation_matrix.print();
    }
}

fn main() 
{
    let _vec: Vec3 = Vec3::new(10, 0.01, "hello".to_string());
    _vec.print();
    
    let _mat: Matrix3x3 = Matrix3x3::new(10, 0.01, "hello".to_string());
    _mat.print();

    let _rot: Rototranslation = Rototranslation::new(_vec, _mat);
    _rot.print();
    
    let mut _vec2: Vec3 = Vec3::new(10, 0.01, "hello".to_string());
    _vec2.print();
    
    let _rotated_vec = _rot.apply_mut(&_vec2);// "&" used because we are expecting _vec2's value change
}
fzsnzjdm

fzsnzjdm1#

是否可以在不使用clone()copy()函数的情况下修复这两个函数?
Yes。问题并不是真正的转换(尽管我确信在其他上下文中它会引起问题,特别是我不知道为什么它会按值获取转换矩阵)。
它是你实现AddSub作为移动操作,对两个参数(又名Trait<T> for T),所以初始减法和最终加法都试图消耗origin_vector,他们不能这样做,因为它只能通过借用访问。
解决办法是:

  1. impl Sub<&Vec3> for &Vec3而不是当前的,这样减法只会借用,replace无论如何都会创建一个新的字符串,所以不需要转移所有权。
  2. impl Add<&Vec3> for Vec3,这样就可以用借用的Vec3添加自己的Vec3,这是尾部添加所需的。
    然后,您还需要分别修复相应表达式的借用。
let transformed_vector = vector - &self.origin_vector;

return transformed_vector + &self.origin_vector;
string: vector.string + &matrix.string,
//why is "&" needed here as we are not modifying matrix.string?

因为标准库实现了Add<&str> for Stringmatrix.string是一个String,所以您需要将其转换为&str(或者足够接近,&String是由于deref强制。
另外,&特别不允许突变,你可能想读一下Rust的书或其他东西?&是一个不可变的引用类型。

pub fn Rototranslation::apply_mut(&self, vector: &Vec3) -> Vec3 
//why is not a "mut" needed here?

因为不管你的命名方案如何,你都没有发生任何变异?Vec3 - Vec3创建了一个新的Vec3Vec3::transform也是如此,还有Vec3 + Vec3。没有看到任何变异。

let transformed_vector = *vector - self.origin_vector;
//why do we need a dereference here?

因为你的impl Add<Vec3> for Vec3,所以你的加法想要通过值接收两个Vec3,但是vector是一个&Vec3。所以类型不匹配。
当然,你会得到一个借用检查错误,因为你不能从一个共享引用中 * 移动 * 一个值(这是你的Add的impl要求的),而且Vec3不是Copy

相关问题