Is a returned value moved or not?

孤街浪徒 提交于 2021-02-19 04:38:27

问题


With this code:

struct Point {
    x: f64,
    y: f64,
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

impl Rectangle {
    pub fn new(x1: f64, y1: f64, x2: f64, y2: f64) -> Rectangle {
        let r = Rectangle {
            p1: Point { x: x1, y: y1 },
            p2: Point { x: x2, y: y2 },
        };
        // some code where r is used
        r
    }
}

let rectangle = Rectangle::new(0.0, 0.0, 10.0, 10.0);

From a memory point of view, is rectangle the same instance as r, or is it a copy of r?

Do I have to explicitly return by reference (something like &r)?

I have to create millions of rectangles, and I don't want there to be useless copies.


回答1:


From a memory point of view, is rectangle the same instance as r, or is it a copy of r?

Unspecified.

The Rust language specifies the semantics of the language, and while they do constrain the implementation somewhat, in this case they do not. How a return value is passed up the call stack is part of the ABI, and not only is the ABI unstable (in Rust), it's also platform specific.

Do I have to explicitly return by reference (something like &r)?

Returning by reference is not possible.

You could return a Box<Rectangle> but the cost of the memory allocation would dwarf the cost of copying a Rectangle in the first place, so it's hardly advisable.

You could force this using output parameters instead, but this has other issues:

  • if you have a &mut Rectangle parameter, you first need to have a valid instance, which has to be initialized; rather wasteful,
  • if you have a *mut Rectangle pointing to uninitialized memory, you need to use unsafe code, hardly satisfying.

However...

I have to create millions of rectangles, and I don't want there to be useless copies.

I think you are worrying for nothing.

The first rule of performance tuning is measure first; and I doubt that you'll be able to observe a performance issue in the creation of those millions of rectangles.

The compiler has multiple tricks up its sleeves, such as:

  • not even materializing the rectangle instance to start with, but pass its components via CPU registers instead,
  • inlining new at the call site, avoiding any copy whatsoever,
  • ...

Thus, before worrying about the cost of copying 4 f64, I would implement the naive solution, compile in release mode, and observe what happens.



来源:https://stackoverflow.com/questions/47346001/is-a-returned-value-moved-or-not

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!