2016-10-23 32 views
7

コードを考えてみましょう:なぜボックス<trait>はボックス<struct>とサイズが異なりますか?

use std::boxed::Box; 
use std::mem::transmute; 

trait Total { 
    fn total(&self) -> i32; 
} 

#[derive(Debug)] 
struct S { 
    a: i32, 
    b: i32, 
    c: i32, 
} 

impl S { 
    fn new() -> S { 
     S { a: 2, b: 3, c: 4 } 
    } 
} 

impl Total for S { 
    fn total(&self) -> i32 { 
     self.a + self.b + self.c 
    } 
} 

fn main() { 
    let b: Box<Total> = Box::new(S::new()); 
    unsafe { 
     let s: Box<S> = std::mem::transmute(b); 
     println!("S = {:?}", s); 
    } 
} 

これはエラーを与える:Box<Total>は本当に私たちは、このエラーを取得しない理由Box<S>であることを考えると

error[E0512]: transmute called with differently sized types: Box<Total> (128 bits) to Box<S> (64 bits) 
    --> src/main.rs:30:29 
    | 
30 |    let s: Box<S> = std::mem::transmute(b); 
    |        ^^^^^^^^^^^^^^^^^^^ 

trait object

+0

「let b:Box 」はどういう意味ですか? – Aurora0001

+0

私は[2番目で明らかに重要性の低い質問](http://meta.stackexchange.com/q/39223/281829)を削除しました。 – Shepmaster

答えて

9

classに仮想ポインタを埋め込んだOO概念を採用しているほとんどの言語とは異なり、Rustは仮想ポインターとstructポインターの両方を運ぶファットポインターアプローチを使用します。

結果、SためBox<Trait>のレイアウトは、次のとおり

+-------+-------+ 
| v-ptr | S-ptr | 
+-------+-------+ 

64ビットプラットフォーム上で128ビットです。あなたはAnyタイプとそのdowncast_refdowncast_mutを使用することができた瞬間に、ダウンキャストについては


詳細については、query_interfaceクレートをご覧ください。

6

、例えばBox<Trait>又は&Traitcontains two pointersとして:データへ

  • ポインタ
  • vtableの
へのポインタ

二つのポインタ(64ビットマシン)は最大128ビットを加算します。

Box<Struct>には、データに直接1つのポインタしか含まれていません。特定のメソッドはコンパイル時に静的に解決できるため、vtableは必要ありません。この単一ポインタはわずか64ビットです。

Given that Box<Total> is really a Box<S>

これらはありません。 の場合、名前が異なるのはなぜですか? :-)

関連する問題