2015-05-23 38 views
17

Bir Option<&T> kullandığınızda, derleyici NULL'un &T ve encodes the None variant as NULL instead için hiçbir zaman olası olmadığını bilir. olmayan bir işaretçi türü ile aynı yaparsanız, orada bu değeri saklamak için hiçbir ekstra bit var ve ekstra alan gereklidir,İşaretçi olmayan kendi türlerim için "boş gösterici optimizasyonu" kullanabilir miyim?

use std::mem; 

fn main() { 
    assert_eq!(mem::size_of::<&u8>(), mem::size_of::<Option<&u8>>()); 
} 

Ancak:

use std::mem; 

fn main() { 
    // fails because left is 1 and right is 2 
    assert_eq!(mem::size_of::<u8>(), mem::size_of::<Option<u8>>()); 
} 

Bu yerden tasarruf sağlayan sağlar Genel olarak, bu doğru. Bununla birlikte, optimizasyona dahil olmayı tercih ediyorum çünkü türümün bazı imkansız değerlere sahip olduğunu biliyorum. Örnek olarak, bir yaşı olan bir oyuncu karakterim olabilir. yaş bilinmeyen olabilir ama yüksek 255 olarak asla: Bu kısıtın optimize edici bilgilendirmek edebilmek istiyorum

struct Age(u8); 

struct Player { 
    age: Option<Age>, 
} 

- Age255 olamaz, yüzden bu bit kullanmak güvenlidir desen None olarak. Mümkün mü?

cevap

13

Hayır, yapamazsın ... ahırda. Bir gecelik derleyiciye gitmeye hazırsanız, core::nonzero::NonZero'u kullanabilirsiniz. Bu, derleyiciye 'un hiçbir zaman bir sıfır içermeyeceğini söyleyen bir sarıcı görevi görür. Aynı zamanda Option<Box<T>> işaretçi boyutunda.

Age'un nasıl oluşturulduğunu gösteren bir örnek ve yükünü okuyun.

#![feature(core)] 
#![allow(dead_code)] 

extern crate core; 

use core::nonzero::NonZero; 

struct Age(NonZero<u8>); 

impl Age { 
    pub fn new(age: u8) -> Age { 
     if age == 0 { panic!("Age cannot be zero!") } 
     Age(unsafe { NonZero::new(age) }) 
    } 

    pub fn age(&self) -> u8 { 
     *self.0 
    } 
} 

struct Player { 
    age: Option<Age>, 
} 

fn main() { 
    println!("size: {}", std::mem::size_of::<Player>()); 
    // Output: size: 1 
} 
+0

Adına göre, 'NonZero' sıfıra değerlerin izin vermediğini varsayardım. Sıfır dışındaki değerler ne olacak? Benim örneğimde, sıfır geçerli olabilir, ancak 255 değil. – Shepmaster

+1

@Shepmaster: 0'a sabit kodlanmış, bir özellik ve bununla bağlantılı sabitleri varsayalım, ama şimdi matematik için yerleşmek zorunda kalacaksınız. Eğer 255 sihirli değerinizse, depolamaya gelen '+ 1 've depolamadan gelen' -1' uygulama (aritmetik sarma ile),' NonZero 'sihrinin çalışması için yeterli olacaktır :) –

+1

@MatthieuM. kesinlikle, gerçekten buna değip değmediğini görmek için daha fazla profil yapmak zorunda kalacağım. Daha az bayt kullanmak bariz bir kazanç gibi görünüyor; her yerde daha az bayt * ve * zorunlu matematik kullanarak daha az emin-ateştir. – Shepmaster