Ödünç alınan içerikten çıkarılamaz / paylaşılan bir referansın arkasından taşınamaz


127

Hatayı anlamıyorum cannot move out of borrowed content. Birçok kez aldım ve her zaman çözdüm, ama nedenini hiç anlamadım.

Örneğin:

for line in self.xslg_file.iter() {
    self.buffer.clear();

    for current_char in line.into_bytes().iter() {
        self.buffer.push(*current_char as char);
    }

    println!("{}", line);
}

şu hatayı üretir:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:31:33
   |
31 |             for current_char in line.into_bytes().iter() {
   |                                 ^^^^ cannot move out of borrowed content

Rust'un yeni sürümlerinde hata şu şekildedir:

error[E0507]: cannot move out of `*line` which is behind a shared reference
  --> src/main.rs:31:33
   |
31 |             for current_char in line.into_bytes().iter() {
   |                                 ^^^^ move occurs because `*line` has type `std::string::String`, which does not implement the `Copy` trait

Klonlayarak çözdüm line:

for current_char in line.clone().into_bytes().iter() {

Aşağıdaki gibi diğer yayınları okuduktan sonra bile hatayı anlamıyorum:

Bu tür bir hatanın kaynağı nedir?


1
Bunun gibi sorulara baktın mı ? (Btw, dizeler .bytes()yöntemi sunar.)
huon

Evet, araştırdım ama anlamadım :( Ve benim dizem bir std :: string :: String, belgelere göre .bytes () yöntemi yok
Peekmo

4
Adı.as_bytes()
bluss

Aslında teşekkür ederim, as_bytes()klonlamadan çalışıyor . Ama hala nedenini anlamıyorum?
Peekmo

Stringalır bytesgelen bir yöntem str.
huon

Yanıtlar:


108

İmzaya bakalım into_bytes:

fn into_bytes(self) -> Vec<u8>

Bu self, self ( &self) ' e bir gönderme değil . Araçlarla O selfedilecek tüketilen ve çağrısından sonra kullanılamayacaktır. Onun yerine bir Vec<u8>. Önek into_, bunun gibi yöntemleri belirtmenin yaygın bir yoludur.

iter()Yöntemin tam olarak ne döndürdüğünü bilmiyorum , ama benim tahminime göre bir yineleyici bitti &String, yani a'ya referanslar döndürüyor Stringama size bunların sahipliğini vermiyor. Bu , değeri tüketen bir yöntemi çağıramayacağınız anlamına gelir .

Bulduğunuz gibi, bir çözüm kullanmaktır clone. Bu o yinelenen bir nesne oluşturur yapmak kendi ve çağırabilir into_bytesüzerinde. Diğer yorumcuların da belirttiği gibi, hangisinin as_bytesalındığını da kullanabilirsiniz &self, böylece ödünç alınan bir değer üzerinde çalışır. Hangisini kullanmanız gerektiği, işaretçiyle ne yaptığınız için nihai hedefinize bağlıdır.

Daha büyük resimde, tüm bunların sahiplik kavramı ile ilgisi var . Bazı işlemler öğeye sahip olmaya bağlıdır ve diğer işlemler nesneyi ödünç almakla (belki de değişebilir şekilde) kurtulabilir. Bir referans ( &foo) sahiplik sağlamaz, sadece ödünç alır.

Bir fonksiyonun argümanları selfyerine kullanmak neden ilginç &self?

Sahipliği devretmek genel olarak yararlı bir kavramdır - bir şeyle işim bittiğinde başkası sahip olabilir. Rust'ta daha verimli olmanın bir yolu. Bir kopya ayırmaktan, size bir kopya vermekten ve ardından kopyamı atmaktan kaçınabilirim. Mülkiyet aynı zamanda en müsamahakâr devlettir; bir nesneye sahipsem, istediğim gibi yapabilirim.


İşte test etmek için oluşturduğum kod:

struct IteratorOfStringReference<'a>(&'a String);

impl<'a> Iterator for IteratorOfStringReference<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<Self::Item> {
        None
    }
}

struct FileLikeThing {
    string: String,
}

impl FileLikeThing {
    fn iter(&self) -> IteratorOfStringReference {
        IteratorOfStringReference(&self.string)
    }
}

struct Dummy {
    xslg_file: FileLikeThing,
    buffer: String,
}

impl Dummy {
    fn dummy(&mut self) {
        for line in self.xslg_file.iter() {
            self.buffer.clear();

            for current_char in line.into_bytes().iter() {
                self.buffer.push(*current_char as char);
            }

            println!("{}", line);
        }
    }
}

fn main() {}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.