Rust 是否移动了返回值?

Rust 是否移动了返回值?,rust,Rust,使用此代码: 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: y

使用此代码:

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);
从内存的角度来看,
rectangle
是与
r
相同的实例,还是它是
r
的副本

我是否必须通过引用显式返回(类似于
&r

我必须创建数百万个矩形,我不希望有无用的副本

从内存的角度来看,
rectangle
是与
r
相同的实例,还是它是
r
的副本

未指定

Rust语言指定了该语言的语义,虽然它们在某种程度上限制了实现,但在本例中它们没有。返回值如何向上传递到调用堆栈是ABI的一部分,不仅ABI不稳定(在Rust中),而且是特定于平台的

我是否必须通过引用显式返回(类似于
&r

您可以返回一个
,但内存分配的成本首先会使复制
矩形
的成本相形见绌,因此这几乎是不可取的

您可以使用输出参数强制执行此操作,但这还有其他问题:

  • 如果您有一个
    &mut Rectangle
    参数,那么首先需要有一个有效的实例,该实例必须初始化;相当浪费,
  • 如果有一个
    *mut矩形
    指向未初始化的内存,则需要使用
    不安全的
    代码,这很难令人满意
然而

我必须创建数百万个矩形,我不希望有无用的副本

我想你是在无缘无故地担心。

性能调整的第一条规则是先测量;我怀疑你是否能在创建数百万个矩形的过程中观察到性能问题

编译器有多种技巧,例如:

  • 甚至不具体化要开始的
    矩形
    实例,而是通过CPU寄存器传递其组件
  • 在呼叫站点内联
    new
    ,避免任何拷贝

因此,在担心复制4
f64
的成本之前,我会实现一个简单的解决方案,在发布模式下编译,并观察会发生什么。

当复制“事实上”发生时,Rust Gurante调用
drop()
释放原始值的资源吗?@Mergasov:我认为你的心智模型是错误的。锈菌有两种操作,由两个特征识别:
Clone
Copy
。创建
克隆时,您(用户)指定创建克隆所涉及的逻辑;例如,对于
字符串
,它意味着分配第二个缓冲区并将第一个缓冲区的内容复制到那里。克隆后,两个实例都独立生活。如果不需要键入
.clone()
,Rust只需移动实例。如果移动实例,则不会删除该实例。如果复制了一个实例(
Copy
),则删除是不可操作的。@Mergasov:因此,可以保证反之。Rust保证当它位复制一个值时(无论是移动还是
Copy
ing),它永远不会调用
Drop