質問: プログラム言語を作ってます。 その際にstringの扱いで止まりました。 参照型はそこにポインタがはいってる。 値型にはそこにそのまま値が入ってる。 の形です。 値型のメリットは、 アクセスが早い デメリットは stringは性質上可変長のため構造体やオブジェクトの長さが同じクラスでも変わる stringの長さが変わるたびにめもりをオブジェクトごと確保し直さなければいけないこと 参照型のメリットは オブジェクトの長さが固定にできる メモリの再確保の時にコピーするバイト数が減ること デメリットは アクセスが遅い と思ってます。 そこでどちらを採用すると良さそうかを皆さんに聞きたいと思ってここでしつもんしました。 聞きたいとは string は参照型にすべきか値型にすべきかです。
回答: スタックのような値を保持するなんらかの場所を持ち、かつ参照型を「実体をヒープにおいて、それを示す値はスタック上にヒープアドレスを置く」また値型を「実体そのものをスタック上に置く」と仮定します。 自分の意見は「文字列のような可変(あるいは大きなサイズを持つもの)は参照型一択」です。 参照型のメリットについてですが * 値がコピーされるため特定のスコープ内にしか影響が及ばない string s := 'a' call func(s) などとしたときに例えfuncの中で引数が更新されても元のsの値は変わらないといった利点です。 しかしこの特性の実現には他にも解決法があります。stringをimmutableなものにすれば参照型であっても前述の特性は獲得できます。これはC#やjavaで取られている方法ですね。lispではstringが単なる文字の配列(そして配列は参照型相当)ですが必要に応じて「更新不可能な文字配列」を作るというテクニックで同様のことを実現しています。 * ヒープを消費しない 値型にするとヒープは消費しませんが、そのかわり関数引数や変数への代入など値を引き渡す際に必ず内容をコピーすることになるでしょう。小さなサイズであれば問題はありません。しかし大きなサイズになってくるとコピーのオーバーヘッドが耐え難いものになる恐れが大だと思います。 * サイズの問題 スタックに値を割り付ける際にどうしてもデータのサイズを特定することが必要です。そうすると異なるサイズの構造は異なる型にしないと管理できません。 string(10) a := 'abcdef' のような宣言になることでしょう。DBMSでは基本的にデータを値型としてrowの領域へ詰めて管理するためにこのような考え方になっていると思います。汎用言語でも同様の考え方にすることはできると思います。ただ静的な型付けの言語とするならstring(10)とstring(20)を同じ型として扱うか扱わないかや、同じ型なのに異なるサイズを持つ値型をどうやって統一的に扱うか(例えば単一の関数の引数にどうやって渡すか)を解決することを考えないければなりません。そのあたりを考えるとどうしても文字列型の「アドレス」という概念を持ち出さざるを得ません。(持ち出しても別にかまわないのですが。C,C++はそうしていますし) 以上を色々考えるとデリファレンスが1回少ないという程度のアクセス速度の違いよりも「常に同一のサイズとして扱える」ということの方が自分には重要に見えます。多くの言語が文字列や配列のようなものを「参照で扱える」としている事実はどの設計者もそれを重視しているからではないでしょうか?