简体   繁体   English

在类似 function Rust 的构造函数中为许多结构成员分配参数值

[英]Assign a parameter value to many struct members in a contructor similar function Rust

I have an issue with a simple struct creation with generic type, as follows:我在使用泛型类型创建简单结构时遇到问题,如下所示:

struct Point3<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T> Point3<T>
{
    fn create3(vx: T, vy: T, vz: T) -> Point3<T> {
        Point3::<T> {
            x: vx,
            y: vy,
            z: vz,
        }
    }

    fn create1(v: T) -> Point3<T> {
        Point3::<T> {
            x: v,
            y: v,
            z: v,
        }
    }
}

but when I tried to compile it, I got an error:但是当我尝试编译它时,我得到了一个错误:

fn create1(v: T) -> Point3<T> {
   |                - move occurs because `v` has type `T`, which does not implement the `Copy` trait
34 |         Point3::<T> {
35 |             x: v,
   |                - value moved here
36 |             y: v,
   |                ^ value used here after move

I understand than v is moved in x and so not available for y or z .我了解vx中移动,因此不适用于yz so it seems I need to copy it, but I don't know how to do that, nor implement the Copy trait for T since its a generic type所以看来我需要复制它,但我不知道该怎么做,也不知道TCopy特性,因为它是通用类型

If I pass v by ref I have another error如果我通过 ref 传递v我有另一个错误

I'm sure it's pretty simple, but as ac/c++ dev rust is complex to me for the moment:)我敢肯定它很简单,但是 ac/c++ dev rust 目前对我来说很复杂:)

When working with type parameters, the only thing that Rust assumes about the type is that it is Sized .使用类型参数时,Rust 唯一假设的类型是它是Sized Any other constraints on the type parameter must be explicitly written out.必须明确写出对类型参数的任何其他约束。

Also, Rust's default move semantics mean that a value can have only a single owner, and that once a value is "moved out of" a place, it is no longer valid there.此外,Rust 的默认移动语义意味着一个值只能有一个所有者,并且一旦一个值被“移出”一个地方,它就不再有效。 You can opt out of this behaviour by implementing Copy , though this is only valid for types that can be meaningfully memcpy -ed, so many things can't use this (anything with a Drop impl, &mut T , and more).您可以通过实现Copy来选择退出此行为,尽管这仅对可以有意义地memcpy -ed 的类型有效,因此很多东西不能使用它(任何带有Drop impl、 &mut T等的东西)。 TLDR, it's a fairly restrictive bound to put on an API. TLDR,穿上 API 是一个相当严格的限制。

The much more general case is Clone , which is a supertrait of Copy (which means: any T that implements Copy , also implements Clone ).更一般的情况是Clone ,它是Copy的超特征(这意味着:任何实现CopyT也实现Clone )。 The difference is that Clone is potentially an expensive operation, potentially requiring heap allocations, and must be explicitly called via Clone::clone , but the tradeoff is that it is far more widely applicable.不同之处在于Clone可能是一项昂贵的操作,可能需要堆分配,并且必须通过Clone::clone显式调用,但代价是它的适用范围要广得多。

So I'd suggest rewriting your code as follows:所以我建议按如下方式重写您的代码:

// this function doesn't need to impose any special bounds on T,
// since it never needs to be cloned
impl<T> Point3<T> {
  fn create3(x: T, y: T, z: T) -> Self {
    Self { x, y, z }
  }
}

// this function does require clone, so we have to add the bound
impl<T: Clone> Point3<T> {
  fn create1(v: T) -> Self {
    Self {
      x: v.clone(),
      y: v.clone(),
      z: v,
    }
  }
}

This allows your API to be used by significantly more types, but also doesn't add any performance overhead for Copy types, since the Clone implementation for a type that is also Copy is basically a standard memcpy .这允许您的 API 被更多的类型使用,但也不会为Copy类型增加任何性能开销,因为同样是Copy的类型的Clone实现基本上是标准的memcpy

Admittedly, with a struct called Point3 , it's probably only going to be used for numbers, so the Copy vs Clone distinction isn't very relevant, but in the general case, a Clone bound is more widely usable.诚然,对于名为Point3的结构,它可能只会用于数字,因此CopyClone的区别不是很相关,但在一般情况下, Clone边界的使用范围更广。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM