Does passing a String to a function by value move its pointer, length, and capacity without copying the heap data, just like let s2 = s1?

fn main() {
    let s1 = String::from("ganesha");

    // The String's metadata (pointer, length, and capacity)
    // is moved to s2; the actual heap data ("ganesha") is not copied.
    // so both will point same and single heap data.
    // let s2 = s1;

    //My question is: does the same thing happen when passing s1 this way to func
    take_ownership(s1);

    // println!("{s1}"); // Error: s1 was moved
}

fn take_ownership(s2: String) {
    println!("{s2}");
}

Yes, that’s one of the key points of move semantics. Of course, after optimization there may not be any moves or function call at all.

Yes. In Rust, everything is moved by default, and never copied except for two cases:

  • This is a cheap object that implements Copy trait.
  • You call clone explicitly.

This is a nice thing, because it saves us from creating huge copies by accident (as it happened sometimes in C++ especially in pre C+11 era)

thanks for droping my confusion.
great answer
once again thanks for this clear/great/well detailed/to the point ans

thanks for your valuabe time
i have recently started so sorry to say not understood by your ans

This is a cheap object that implements Copy trait.

to be precise the requirement is it implements Copy which has the requirement that you can clone it by just copying the underlying bytes without calling any special function (e.g. you can just memcpy it).

I would not consider [u8; 1_000_000] to be "cheap", but it implements Copy.

Sorry, what I meant was just that the ownership taking without having to copy a whole string is one of the big reasons Rust has this ownership taking in the first place :slight_smile: The technical term for this type of mechanism is "move semantics".

Fortunately there's at least a warn by default rustc lint for that: