12

私が理解していることから、Nim の文字列は基本的に変更可能な一連のバイトであり、割り当て時にコピーされるということです。

それを考えると、私はそれsizeofが(のようにlen)バイト数を教えてくれると思いましたが、代わり8に私の64ビットマシンでは常に与えられるので、ポインタを保持しているようです。

それを踏まえて、以下の質問があります...

  • 課題のコピーの背後にある動機は何でしたか? それらが可変だからですか?

  • 割り当てられたときにコピーされないことがありますか? (var関数以外のパラメータはコピーされないと思います。他に何かありますか?)

  • 変異した場合にのみ実際にコピーされるように最適化されていますか?

  • 文字列とシーケンスの間に大きな違いはありますか、それとも上記の質問に対する答えはすべてのシーケンスに等しく適用できますか?

  • 一般的に注目に値するものはありますか?

ありがとうございました!

4

1 に答える 1

14

文字列の定義は、実際にはsystem.nim別の名前のすぐ下のにあります。

type
  TGenericSeq {.compilerproc, pure, inheritable.} = object
    len, reserved: int
  PGenericSeq {.exportc.} = ptr TGenericSeq
  UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char]
  # len and space without counting the terminating zero:
  NimStringDesc {.compilerproc, final.} = object of TGenericSeq
    data: UncheckedCharArray
  NimString = ptr NimStringDesc

lenしたがって、文字列は, reservedanddataフィールドを持つオブジェクトへの生のポインターです。文字列のプロシージャはsysstr.nimで定義されています。

文字列割り当てのセマンティクスは、デフォルトで Nim のすべての値型 (ref または ptr ではない) と同じになるように選択されているため、割り当てによってコピーが作成されると想定できます。コピーが不要な場合、コンパイラはそれを除外できますが、これまでのところ、それがどの程度起こっているかはわかりません。文字列を proc に渡してもコピーされません。変更されるまで文字列のコピーを防止する最適化はありません。シーケンスも同じように動作します。

文字列と seq を浅いとしてマークすることで、デフォルトの割り当て動作を変更できます。その後、割り当て時にコピーは行われません。

var s = "foo"
shallow s
于 2015-04-02T11:11:54.847 に答える