2016-05-19 13 views
8

Basit bir yardımcı yöntemden, aşırı yüklenme kullanan bir sınıf kullanırken bir derleme hatası alıyorum. İşte kendine yeten bir testtir (benim gerçek koddan basitleştirilmiş, ama yine de sorunu gösteren): Ben Rust 1.8 ile bu derlemek çalışıyorum"Ödünç alınan içeriğin dışına çıkamıyor" kullanıcı aşırı yüklendi

use std::ops::{Add, Sub, Neg, Mul, Div}; 

#[derive(Debug, Eq, PartialEq)] 
pub struct Money { 
    cents: i64, 
} 
impl Money { 
    pub fn new(cents: i64) -> Money { 
     Money { cents: cents } 
    } 
} 
impl Add for Money { 
    type Output = Money; 
    fn add(self, other: Money) -> Money { 
     Money { cents: self.cents + other.cents } 
    } 
} 
impl Mul<Money> for f64 { 
    type Output = Money; 
    fn mul(self, rhs: Money) -> Money { 
     Money { cents: (self * rhs.cents as f64) as i64 } 
    } 
} 

#[derive(Debug)] 
pub struct AbsOrPerc { 
    pub absolute: Money, 
    pub percent: f64, 
} 
impl AbsOrPerc { 
    pub fn new(abs: Money, perc: f64) -> AbsOrPerc { 
     AbsOrPerc { 
      absolute: abs, 
      percent: perc, 
     } 
    } 

    pub fn total(&self, basis: Money) -> Money { 
     // This works: 
     // Money::new((self.absolute.cents as f64 + self.percent * basis.cents as f64) as i64) 
     // This doesn't: 
     self.absolute + self.percent * basis 
    } 
} 

ama bu hatayı alıyorum:

src/lib.rs:42:5: 42:9 error: cannot move out of borrowed content [E0507] 
src/lib.rs:42  self.absolute + self.percent * basis 

Rust Kitabını ve sahiplik ve borçlanma ile ilgili parçaları okudum. Bu soru, ör .:

Cannot move out of borrowed content

hata aynı iken, koşullar farklı olduğu için kendi soru yineleniyor sanmıyorum hakkında burada StackOverflow'daki sayıda soru okudum. Ayrıca, diğer soruların buna nasıl uygulandığını bilsem, sormam gerekmeyecek. :-)

Benim sorum şu: Bu hatayı nasıl çözebilirim? &self'u self olarak değiştirmek istemiyorum, çünkü bu başka sorunlara neden oluyor. Sadece sorunu çözmekle kalmanın yanı sıra, Rust'un ne korktuğunu bilmek isterim. Burada herhangi bir tehlike görmüyorum.

+0

bakınız http://stackoverflow.com/q/28595075/155423, http://stackoverflow.com/q/29926724/155423, http://stackoverflow.com/q/30974593/155423, http://stackoverflow.com/q/28527702/155423, http://stackoverflow.com/q/34621969/155423 ve http://stackoverflow.com/Q/28843931/155423. – Shepmaster

cevap

8

Operatörleri, &Money yerine Money yerine uyguluyorsunuz. Bu, operatörün işlenenlerinin sahipliğini alacağı anlamına gelir. Bu nedenle, total'da eki gerçekleştirmek için, self.absolute'u taşımanız gerekir, bu izin verilmeyen bir işaretçiden (yalnızca sahip olduğunuz değerleri taşıyabilirsiniz) taşınamadığından izin verilmez. Copy (i32 ya da f64 gibi temel öğeler için geçerli olan) türleri kopya kopyalarını uygular; aksi halde değerini taşır, bu da kaynağın hareket edildikten sonra kullanılamaz olacağı anlamına gelir. senin Money yapı gerçekten sadece bir cents alan içeriyorsa

, ben bunu (ayrıca Copy uygulamak dahi iyi bir fikir uygulamak olacaktır Clone, uygulayıcı gerektiren) Copy uygulamak yapmak önerilir. Sen #[derive] ile kolayca Copy ve Clone uygulayabilirsiniz: Şimdi

#[derive(Copy, Clone, Debug, Eq, PartialEq)] 
pub struct Money { 
    cents: i64, 
} 

, total yılında, yerine self.absolute hareketli, Pas yerine bu kopyalar. Copy uygulayamıyorsanız, self.absolute'u self.absolute.clone() ile değiştirin.


Eğer &Money üzerinde operatörleri uygulamaya olsaydı, o zaman sadece Money değerlere göndermeler geçebileceği. Örneğin, bu tip uygulamalara, total böyle uygulanabilir:

pub fn total(&self, basis: Money) -> Money { 
    &self.absolute + &(self.percent * &basis) 
} 
+0

Sahiplik ve "Ekle" nin, ekleri değerlere göre harcadığı gerçeğine, belki de böyle bir şeyin neden yararlı olduğuna ve hatta bir referansta "Ekle" nin uygulanmasının neden birinin 'Kopya' uygulamasının uygulanmasına engel olacağına dair yorum yapmaya değer olabilir. ihtiyaçları vardı. – Shepmaster

+0

Rust'un, varsayılan olarak (sadece ödevlerde olduğu gibi, satırlarda olduğu gibi) Rust'u yeniden çağırmayı hak ettiğini düşünüyorum; bu, referans olarak genellikle yeni gelenlere yabancıdır. İyi cevap. –

+0

Bu harika cevap için teşekkür ederim. Kopyala/taşı/ödünç al yavaşça batar. Bu cevap çok yardımcı olur! Ayrıca pedagojik olarak, ikililerin anlaşılması daha kolaydır ve Kitap asla benim bildiğim kadarıyla onlara (Kopyaya karşı Kopyala) Borrow'a benzetir - her zaman ikiye ayrılır ve üçüncü olarak bahsetmez. Üçünü bir araya getirmek çok faydalıdır. –

İlgili konular