3

Dのコンテナーには、デフォルトで値または参照のセマンティクスがありますか?それらが参照セマンティクスを持っている場合、次の(学術的な)例のように、Dでの関数型プログラミングスタイルの使用を根本的に妨げることはありません(C ++11のMoveSemanticsと比較して)。

auto Y = reverse(sort(X));

Xコンテナはどこですか。

4

2 に答える 2

4

コンテナに値セマンティクスがあるか参照セマンティクスがあるかは、コンテナに完全に依存します。組み込みのコンテナーは、動的配列、静的配列、および連想配列のみです。静的配列はスタック上にあるため、厳密な値のセマンティクスがあります。連想配列には、厳密な参照セマンティクスがあります。そして、動的配列は主に参照セマンティクスを持っています。それらは要素であり、コピーされませんが、コピーされるため、少し特殊なセマンティクスになります。詳細については、Dアレイに関するこの記事を読むことをお勧めします。

公式であるが組み込みではないコンテナーに関しては、std.container内のコンテナーはすべて参照セマンティクスを持っており、そうでない場合は非常に非効率的であるため、一般に、コンテナーはそのようになります。ただし、誰でも独自のコンテナを実装できるため、必要に応じて、値型のコンテナを作成できます。

ただし、C ++のように、Dは、アルゴリズムがコンテナーで動作するというルートを取りません。アルゴリズムに関する限り、コンテナーに参照または値のセマンティクスがあるかどうかはほとんど関係ありません。C ++では、アルゴリズムはイテレータで動作するため、コンテナを並べ替える場合は、のような操作を行いますsort(container.begin(), container.end())。Dでは、それらは範囲で動作するので、あなたはそうするでしょうsort(container[])。どちらの言語でも、実際にはコンテナを直接ソートしません。したがって、コンテナ自体に値があるか参照セマンティクスがあるかは、通常のアルゴリズムとは無関係です。

ただし、Dは、範囲がそれに適しているため、C++よりもアルゴリズムを使用した関数型プログラミングの方が優れています。イテレータはペアで渡す必要がありますが、これはチェーン機能にはあまり適していません。一方、範囲は非常にうまく連鎖し、Phobosはこれを利用します。その主要な設計原則の1つは、その関数のほとんどが範囲で動作し、通常はパイプを使用してunixコマンドラインで実行することをコードで実行できるようにすることです。ここでは、出力を生成する多くの汎用ツール/関数があります。他のツール/関数にパイプ/パスして操作することができます。これにより、直接必要なことを正確に実行するプログラム/関数を誰かが作成することに頼るのではなく、独立した操作をチェーンしてニーズに固有のことを実行できます。ウォルターブライトは最近それについてこの記事

したがって、Dでは、次のようなことを簡単に行うことができます。

auto stuff = sort(array(take(map!"a % 1000"(rndGen()), 100)));

または、UFCS(Universal Function Call Syntax)を使用する場合:

auto stuff = rndGen().map!"a % 1000"().take(100).array().sort();

いずれの場合も、0から1000までの100個の乱数のソートされたリストを生成し、コードは機能的なスタイルであり、C ++はこれを行うのがはるかに困難であり、イテレーターや範囲ではなくコンテナーで動作するライブラリーはやるのはさらに難しい。

于 2012-10-31T18:34:39.193 に答える
2

内蔵コンテナ

Dに組み込まれているコンテナは、スライス(配列/動的配列とも呼ばれます)と静的配列のみです。後者には値のセマンティクスがあります(CやC ++とは異なります)-配列全体が渡されるときに(浅く)コピーされます。

スライスに関しては、間接的な値型であるため、値と参照の両方のセマンティクスを持っていると言えます。

このように想像T[]してみてくださいstruct

struct Slice(T)
{
    size_t length;
    T* ptr;
}

ここptrで、はスライスの最初の要素へのポインタであり、lengthはスライスの境界内の要素の数です。.ptrスライスのフィールドとフィールドにアクセスできます.lengthが、データ構造は上記と同じですが、実際にはコンパイラが組み込まれているため、どこにも定義されていません(名前Sliceは説明のためだけのものです)。

これを知っていると、スライスのコピー(別の変数への割り当て、関数への受け渡しなど)は、長さ(インデクションなし-値セマンティクス)とポインター(間接参照-参照セマンティクス)をコピーするだけであることがわかります。

つまり、スライスは配列(メモリ内の任意の場所にある)へのビューであり、同じ配列への複数のビューが存在する可能性があります

アルゴリズム

sort可能な限り多くのユーザーに対応するために、現場での作業からreversestd.algorithmユーザーが結果をスライスのGCに割り当てられたコピーに入れ、元のコピーを変更しないようにしたい場合は、簡単に実行できます(X.dup)。ユーザーが結果をカスタム割り当てのバッファーに入れたい場合は、それも実行できます。最後に、ユーザーがその場で並べ替えたい場合、これはオプションです。いずれにせよ、余分なオーバーヘッドは明示的になります。

ただし、標準ライブラリのほとんどのアルゴリズムはミューテーションを必要とせず、関数型プログラミングの特徴である遅延評価された範囲の結果を返すことに注意することが重要です。

ユーザー定義のコンテナー

ユーザー定義のコンテナーに関しては、必要なセマンティクスを持つことができます。Dでは任意の構成が可能です。

のコンテナは、コピーを作成するためのメソッドをstd.container持つ参照型で.dupあるため、スライスをわずかにエミュレートします。

于 2012-10-31T16:06:06.087 に答える