ref和所有权转让均无效时如何退货

时间:2019-06-16 14:47:11

标签: rust ownership borrowing

所以,如果我退回这个

self.string_ref.unwrap().as_ref()

编译器会说

error[E0515]: cannot return value referencing temporary value
returns a value referencing data owned by the current function

如果我退货了

*self.string_ref.unwrap().as_ref()

编译器会说

error[E0507]: cannot move out of borrowed content

这让我发疯了

下面是代码:(playground

use std::ptr::NonNull;

struct A {
    string_ref: Option<NonNull<String>>,
}

struct Number {
    num: i32
}

impl A {
    fn hello() {

    }

    fn give_me_string(&self) -> String {
        unsafe {
            *self.string_ref.unwrap().as_ref()
        }
    }
}

fn main() {
    let a = A {
        string_ref: NonNull::new(&mut String::from("hello world") as *mut String)
    };
    let t = a.give_me_string();
    println!("{}", t)
}

2 个答案:

答案 0 :(得分:0)

将示例扩展到最低限度:

struct A {
    string_ref: Option<NonNull<String>>,
}
impl A {
    fn give_me_string(&self) -> String {
        unsafe {
            *self.string_ref.unwrap().as_ref()
        }
    }
}

这里有一些错误:

  1. 最明显的是,即使您仅借用了self.string_ref,您仍在尝试拥有self的所有权。
    为了解决这个问题,您需要使用match语句,该语句可让您解构self.string_ref而不消耗它:
fn give_me_string(&self) -> String {
    unsafe {
        match self.string_ref {
            Some(x) => x.as_ref(),
            None => panic!("Had no `string_ref`!")
        }
    }
}
  1. as_ref返回&T,所以您不能返回拥有的字符串,而是需要克隆它并然后返回拥有的字符串,或引用它:
//Option one: Clone contents
match self.string_ref {
    Some(ref x) => x.as_ref().clone(),
    _ => //...
}
//Option two: Return reference. 
fn give_me_string(&self) -> &str {
    unsafe {
        match &self.string_ref {
            Some(x) => x.as_ref() as _,
            _ => //...
        }
    }
}

要解决注释中提到的另一个问题,请在main函数中添加以下语句:

string_ref: NonNull::new(&mut String::from("hello world") as *mut String)

由于其性质,这将导致UB。您正在使用String来构成String::from,但并未将其值存储在任何地方,而是立即转换为指针。这将在行尾释放String,从而导致UB

答案 1 :(得分:0)

因此,由于有了@Optimistic Peach,我基本上就知道了发生了什么事

Unspecified error..