首页 文章

如何从实现Drop trait的结构中移出一个字段?

提问于
浏览
21

这是一个无效的Rust程序(Rust版本1.1),其中包含一个执行HTTP客户端请求的函数,只返回 Headers ,删除响应中的所有其他字段 .

extern crate hyper;

fn just_the_headers() -> Result<hyper::header::Headers, hyper::error::Error> {
    let c = hyper::client::Client::new();
    let result = c.get("http://www.example.com").send();
    match result {
        Err(e) => Err(e),
        Ok(response) => Ok(response.headers),
    }
}

fn main() {
    println!("{:?}", just_the_headers());
}

以下是编译器错误:

main.rs:8:28: 8:44 error: cannot move out of type `hyper::client::response::Response`, which defines the `Drop` trait
main.rs:8         Ok(response) => Ok(response.headers),
                                 ^~~~~~~~~~~~~~~~
error: aborting due to previous error

我理解为什么借用检查器不接受这个程序,即 drop 函数在移动了 headers 成员之后将使用 response .

我的问题是:我怎样才能解决这个问题并且仍然拥有安全的Rust代码?我知道我可以通过 clone() 进行复制,如下所示:

Ok(response) => Ok(response.headers.clone()),

但是,来自C,这似乎效率低下 . 为什么移动应该足够复制?我想在C中执行类似下面的操作来强制调用移动构造函数(如果可用):

headers_to_return = std::move(response.headers);

有没有办法放弃Rust中的副本而是强行移动,类似于C?

1 回答

  • 21

    您可以使用std::mem::replace()将字段与新的空白值交换,以便将所有权转让给您:

    extern crate hyper;
    
    fn just_the_headers() -> Result<hyper::header::Headers, hyper::error::Error> {
        let c = hyper::client::Client::new();
        let result = c.get("http://www.example.com").send();
        match result {
            Err(e) => Err(e),
            Ok(mut response) => Ok(std::mem::replace(&mut response.headers, hyper::header::Headers::new())),
        }
    }
    
    fn main() {
        println!("{:?}", just_the_headers());
    }
    

    在这里,我们用一组新的空 Headers 替换 response.headers . replace() 返回在替换之前存储在字段中的值 .

相关问题