2017-09-30 12 views
1

可変変数を使用するとメモリが浪費されるのではないかと思います。変数として変数を渡すとメモリが浪費されますか?

はその出力(値ab、及びc)が同一でなければならない、次の2つの例を考える:Example 1

// Example 1 

let mutable mut = Map.empty 

mut <- mut |> Map.add "A" 0 
let fA (m: Map<string,int>) x = m.["A"] + x 
let a = fA mut 0 // 0 

mut <- mut |> Map.add "B" 1 
let fB (m: Map<string,int>) x = m.["A"] + m.["B"] + x 
let b = fB mut 0 // 1 

mut <- mut |> Map.add "C" 2 
let fC (m: Map<string,int>) x = m.["A"] + m.["B"] + m.["C"] + x 
let c = fC mut 0 // 3 

各関数が可変引数を取り、(私は推測)コピーを作成する必要がありますその議論の が合計3部作成されます。

// Example 2 
let mutable mut = Map.empty 

mut <- mut |> Map.add "A" 0 
mut <- mut |> Map.add "B" 1 
mut <- mut |> Map.add "C" 2 

let fA (m: Map<string,int>) x = m.["A"] + x 
let fB (m: Map<string,int>) x = m.["A"] + m.["B"] + x 
let fC (m: Map<string,int>) x = m.["A"] + m.["B"] + m.["C"] + x 

let immut = mut 

let a = fA mut 0 // 0 
let b = fB mut 0 // 1 
let c = fC mut 0 // 3 

Example 2では、各関数は同じ不変の引数のコピーを作成します。 おそらくコンパイラはこれらのコピーを作成するときに追加のメモリを使用しないほどスマートです。各コピーについては、元のオブジェクトへのポインタに過ぎません。

Example 1にコピーされたオブジェクトの平均サイズがExample 2の不変オブジェクトよりも小さいにもかかわらず、Example 2では少ないメモリが使用されます。

この理由は正しいですか?

+2

いいえ、何も今までにコピーされません。リファレンスが指し示すデータ構造の変更可能性とリファレンスの変更を混同しています。 –

答えて

3

例では、Map<'K, 'V>の値は不変です。唯一の変更可能なものはの参照であり、現在のMap<'K, 'V>値のインスタンスへの参照を保持しています。コンパイラは値のコピーを作る必要はありません(私は、F#コンパイラが値の型を除いて背後にコピーを作成するケースはないと思います)。

これは、2つの例がほぼ同じであることを意味します。実際の違いは、例2では、​​3つの関数にさらに値を含むマップを渡しているためです。理論上の問題で最高)。

あなたが変更可能なデータ構造を使用して次のようにコードを実装した場合に起こる可能性を示唆している問題(配列のサイズを変更する)と明示的なコピー:

let data = ResizeArray<string * int>() 

data.Add("A", 0) 
let f1 = 
    let lookup = dict data 
    fun x -> lookup.[x] 

data.Add("B", 1) 
let f2 = 
    let lookup = dict data 
    fun x -> lookup.[x] 

f1 "A" // = 0 
f1 "B" // error 
f2 "A" // = 0 
f2 "B" // = 1 
関連する問題