Understanding argument passing to a method and returning allocated object to a calling method

fn main() {
let s = String::from(“hello”); // s comes into scope

takes_ownership(s);             // s's value moves into the function...
                                // ... and so is no longer valid here

} // Here, x goes out of scope, then s. But because s’s value was moved, nothing
// special happens.

fn takes_ownership(some_string: String) { // some_string comes into scope
println!("{}", some_string);
} // Here, some_string goes out of scope and drop is called. The backing
// memory is freed.

How is this implemented in binary code? Is stack is used to copy the argument of a method or function?

If so, didn’t we have perfomance problem in comparance with C++ passing a pointer to a function?
I understand we can use unsafe rust for that. But this means for example everywhere we want to create data structure in a function or method we must copy it using stack too. So everythere we want ot use factory pattern we will use unsafe rust. This means well designed OOP code with good perfomance is always unsafe Rust code. Correct me if i’m wrong please.

Note that String is a wrapper around pointer. If we look at the code:

pub struct String {
    vec: Vec<u8>,
}

And Vec is:

pub struct Vec<T> {
    buf: RawVec<T>,
    len: usize,
}

And RawVec is:

pub struct RawVec<T, A: Alloc = Global> {
    ptr: Unique<T>,
    cap: usize,
    a: A,
}

So finally we are dealing with a pointer here. So the mount of bits copied, if it is copied, is pretty small.

I don’t know Rust well, but what if my object contains 10-20 different data fields?

It is always possible to pass by reference, like &s.

Can we make RawClass with a Class wrapper?

What if we create object and return it?

Creating object and returning it is going to be pass by value, in rust parlance we are returning the ownership of the object to the caller. I am not sure whether that will involve a bytes copy, or compiler will optimize by allocating the space for the returned object in caller’s stack. If it is the former case we can always create the object in heap, Box<T>.