简体   繁体   中英

why does Rust's Add trait take ownership?

I am writing a toy BigInt class, and while I was implementing the Add trait , I noticed that the it takes ownership of both sides. What problem is that trying to solve, as opposed to borrowing them by reference? Since I am using a Vec as the underlying data structure, I cannot implement Copy , and that makes it somewhat cumbersome to use.

An example of a (minor) inconvenience that it causes:

let i = BigInt::new();
//  - move occurs because `i` has type `BigInt`, which does not implement the `Copy` trait
let j = i + 16u32;
//      --------- `i` moved due to usage in operator
let k = i + 32u32;
//      ^ value used here after move

Again, I know I can just use .clone() , but I am curious about in which ways this is helping the programmer.

An example of why it's important to be able to take ownership is so that String + &str can append to the existing string, instead of cloning it first.

You can always implement Add for references and .clone ing inside of them.

struct A;

impl std::ops::Add for A {
    // normal impl
}

impl<'a> std::ops::Add for &'a A {
    // clone and delegate
}


fn main() {
    A + A; // This still compiles
    &A + &A; // This now compiles
    &A + A; A + &A; // These won't compile, but you can add those impls too, if you'd like

}

However, you should probably only do this for Copy types, to avoid the users being surprised by hidden allocations.

For Copy types you'll likely need 4 impls to be able to add both values to references and references to values, as follows:

impl std::ops::Add<T> for T;
impl<'a> std::ops::Add<T> for &'a T;
impl<'a> std::ops::Add<&'a T> for T;
impl<'a, 'b> std::ops::Add<&'a T> for &'b T; // Not sure if two lifetimes are needed here, but shouldn't hurt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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