Rust学习记录 -> 泛型使用:结构体方法,引用和特性


前言

本文就笔者在学习rust泛型使用时遇到的一个问题进行剖析并给出解决办法


提示:以下是本篇文章正文内容,下面案例可供参考

一、问题简述

首先建立如下包含两个未声明特性的结构体,代码如下:

struct str2<T,E> {
    x:T,
    y:E,
}

再对其声明包含的方法:

impl<T,E> str2<T,E> {
    fn get_x(&self) -> &T {
        &self.x
    }

    fn get_y(&self) -> &E {
        &self.y
    }

    fn create<V, W> (self, other: str2<V,W>) -> str2<T,W> {
        str2 {
            x:self.x,
            y:other.y,
        }
    }

问题就出现在对create方法的调用上:
创建实例如下所示(接下来文中的实例均引用此处):

let a = str2 {
        x:5,
        y:0.99,
    };
    let b = str2 {
        x:6,
        y:15.6
    };

在简单的观察和实际编译运行后可以发现,create方法虽然可以将两个具有不同泛型的结构体实例拼接后创建一个新的结构体实例。
但是显然,创建之后原来的两个结构体实例就会被drop掉,笔者认为这在实际生产环境中是无法接受的情况,所以开始了对该方法的改进。

二、改进过程

1.使用不可变引用

改进代码如下:

fn create<V, W> (&self, other: &str2<V,W>) -> str2<T,W> {
        str2 {
            x:self.x,
            y:(*other).y,
        }
    }

在进行如上改进后,本以为可以顺利运行,但是cargo run后发生了报错,具体报错如下所示:

error[E0507]: cannot move out of `self.x` which is behind a shared reference
 --> src/main.rs:9:15
  |
9 |             x:self.x,
  |               ^^^^^^ move occurs because `self.x` has type `T`, which does not implement the `Copy` trait

error[E0507]: cannot move out of `other.y` which is behind a shared reference
  --> src/main.rs:10:15
   |
10 |             y:(*other).y,
   |               ^^^^^^^^^^ move occurs because `other.y` has type `W`, which does not implement the `Copy` trait

原以为是我对引用和解引用的应用出现了偏差,但是经过一系列的检查后发现问题不在这里,而是对泛型的声明出了问题

2.声明泛型特性

改进代码如下:

#[derive(Debug)]
struct str2<T:PartialOrd + Copy,E:PartialOrd + Copy> {
    x:T,
    y:E,
}

impl<T:PartialOrd + Copy,E:PartialOrd + Copy> str2<T,E> {
    fn create<V:PartialOrd + Copy,W:PartialOrd + Copy> (&self,other:&str2<V,W>) -> str2<T,W> {
        str2{
            x:self.x,
            y:(*other).y,
        }
    }
}

在刚刚学习泛型时,示例中对涉及的泛型均作了特性的声明,这让我开始怀疑一件事情:是否在使用泛型时,如不提前声明特性,则默认所有泛型实例不具有任何特性?

于是我本着试试的想法,为结构体和方法中的泛型声明添加了特性声明,在编译运行后发现解决了报错问题,成功将两个实例拼接成了第三个新实例并且完整保留了两个旧实例。

fn main() {
    let a = str2 {
        x:5,
        y:0.99,
    };
    let b = str2 {
        x:6,
        y:15.6
    };

    let ab = a.create(&b);

    println!("{:#?}",ab);
    println!("{:?}",a);
    println!("Hello, world!");
}

运行结果如下:

    Finished dev [unoptimized + debuginfo] target(s) in 0.39s
     Running `target/debug/re_stru_T`
str2 {
    x: 5,
    y: 15.6,
}
str2 { x: 5, y: 0.99 }
Hello, world!


总结

综上,笔者在解决该问题过程中回顾了引用与解引用的知识,拜读了一些优秀的文章,对泛型在结构体和方法中的使用更熟悉了一些,明白特性在泛型中的特殊性质。如有错误,还请各位大佬指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值