Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有关解引用会获得所有权的理解 #39

Closed
am009 opened this issue Jul 7, 2020 · 3 comments
Closed

有关解引用会获得所有权的理解 #39

am009 opened this issue Jul 7, 2020 · 3 comments
Labels
learning Learner discussions

Comments

@am009
Copy link

am009 commented Jul 7, 2020

之前突然搜到了clone和解引用之间的关系:
rust-lang/rust-clippy#2870
里面说解引用会复制一份再获得所有权, 感到有点神奇.
然后就想到了书上的解引用这一节,
image
这里我之前看的时候没仔细想, 书上既然说解引用会获得所有权, 而后面又说这是绝对不允许的, 那是不是说就不能解引用?
对于实现了Copy trait的类型, 解引用会复制一份再获得所有权也还说得过去, 那对于没有实现的, pass by reference的类型呢?
我查到了下面这篇文章,
https://blog.kevinwmatthews.com/rust-ownership-and-dereferencing/
最后明确说不能通过解引用来获取原来对象的所有权。

最后我得到的结论是, 星号解引用只能用在实现了copy trait(按值复制)的对象的引用上, 然后复制一份并获得所有权。
而对于没有实现按值复制的, 那些"传递指针"的类型的引用, 无论有没有mut, 都完全不能解引用。
这样理解有没有什么问题?

虽然可能什么也不能证明, 我尝试了下面这样的代码, 能够通过编译。

fn main() {
    let mut s = std::string::String::from("123123");
    let mut s2 = &(*(&s));
    println!("{}", s2)
}
fn main() {
    let mut s = std::string::String::from("123123");
    let mut s2 = &mut (*(&mut s));
    s2.insert_str(0, "Hello ");
    println!("{}", s);
    // println!("{}", s2);
}

这里能够解引用我感觉可能是编译器优化,或者因为单纯解引用而不绑定不会转移所有权?

@Tuyixiang Tuyixiang added the learning Learner discussions label Jul 7, 2020
@NameAvailable319
Copy link

我觉得这个本质应该与内存安全有关,你的代码之所以能编译成功应该是因为变量都在同一个函数中,而书中的示例是跨函数的,如果书中的s所有权发生了转移,那么x将会被释放,&x将是一个垂悬引用,rust不允许出现的,而你的代码似乎并不能证明什么,建议尝试一下跨函数的引用和解引用

@jwnhy
Copy link
Contributor

jwnhy commented Jul 8, 2020

你的代码里没有所有权的转移,s 的所有权一直都在 main 函数中。因此怎么解引用实际上都无所谓的。

@am009
Copy link
Author

am009 commented Jul 9, 2020

今天突然发现,我似乎忘了解引用的正常用途,也就是放在赋值左边,作为位置表达式而不是值表达式。

fn main() {
    let mut s = std::string::String::from("123123");
    let s2 = &mut s;
    *s2 = String::new();
    // println!("{}", s2);
}

现在我得到的结论是,

  1. 星号解引用只能用在实现了copy trait(按值复制)的对象的引用上, 然后复制一份并获得所有权。
  2. 而对于没有实现按值复制的, 那些pass by reference的类型的引用, 无论有没有mut, 都完全不能解引用。
  3. 另外, 通过解引用是不可能获得原来被引用的那个对象的所有权的, 这种"盗窃"行为无法实现。
  4. pass by reference时并不是完全不能解引用,解引用还有其他正常的用途。

@am009 am009 closed this as completed Jul 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
learning Learner discussions
Projects
None yet
Development

No branches or pull requests

4 participants