0

私はDでトライを書いていますが、各トライオブジェクトにデータへのポインターを持たせたいのですが、ノードがトライのターミナルノードである場合はNULL以外の値を持ち、それ以外の場合はNULLを持ちます。データのタイプは、トライが作成されるまで決定されません(Cでは、これはで実行されvoid *ますが、テンプレートで実行する予定です)。これが、ヒープオブジェクトへのポインターが望ましい理由の1つです。

これには、最終的にヒープ上にデータを作成する必要があります。その時点で、トライノードがデータを指すことができます。実験してみるとnew、C ++の場合と同じように、このタスクを実行しているようです。ただし、何らかの理由で、これは文字列で失敗します。次のコードが機能します。

import std.stdio;

void main() {
    string *a;
    string b = "hello";
    a = &b;
    writefln("b = %s, a = %s, *a = %s", b, a, *a);
}
/* OUTPUT:
b = hello, a = 7FFF5C60D8B0, *a = hello
*/

ただし、これは失敗します。

import std.stdio;

void main() {
    string *a;
    a = new string();
    writefln("a = %s, *a = %s", a, *a);
}
/* COMPILER FAILS WITH:
test.d(5): Error: new can only create structs, dynamic arrays or class objects, not string's
*/

何が得られますか?ヒープ上に文字列を作成するにはどうすればよいですか?

PS Dコンパイラを書いている人がこれを読んでいる場合、「文字列」のアポストロフィは文法上の誤りです。

4

4 に答える 4

5

文字列は常にヒープに割り当てられます。これは、他の動的配列でも同じです (T[]stringtype の単なるエイリアスですimmutable(char)[])。

ポインタが 1 つだけ必要な場合は、次の 2 つの方法があります。

auto str = "some immutable(char) array";
auto ptr1 = &str; // return pointer to reference to string (immutable(char)[]*)
auto ptr2 = str.ptr; // return pointer to first element in string (char*)

空の文字列へのポインターが必要な場合は、これを使用します。

auto ptr = &"";

文字列内の単一の文字の値を変更できないことに注意してください (それらは であるためimmutable)。文字列内の文字を操作する場合は、次を使用します。

auto mutableString1 = cast(char[])"Convert to mutable."; // shouldn't be used
// or
auto mutableString2 = "Convert to mutable.".dup; // T[].dup returns mutable duplicate of array

通常、何をしているのか完全に理解していない限り、ポインタは避けるべきです。

メモリの観点からは、ポインタは 4B (x64 マシンの場合は 8B) のメモリを使用しますが、配列へのポインタを使用している場合、ポインタが null でない場合、12B (+ 配列内のデータ) のメモリが使用されます。配列参照は 2 つのポインターのセットであるため、ポインターからの場合は 4B、配列への参照からの場合は 8B です。配列の最初の要素と最後の要素に 1 つずつ。

于 2013-02-22T12:12:05.013 に答える
2

覚えておいてstringくださいimmutable(char)[]stringはすでに動的配列であるため、ポインターは必要ありません。

それらの作成に関してはnew char[X]、 ではなく、 を行うだけですnew string

于 2013-02-22T01:00:20.970 に答える
0

正確に1つのポインターしか使用できず、Marmystの回答の提案を使用したくない場合(&str彼の例では、スタックへの参照を作成しますが、これは望ましくない可能性がありstr.ptr、D文字列が常にゼロであるとは限らないため、文字列の長さに関する情報が失われますこれを行うことができます:

D 配列 (したがって文字列) は、データ ポインターと長さメンバーを持つ構造体と考えることができることを思い出してください。

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

そのため、配列を扱う場合、配列の内容は常にヒープ上にありますが、ptr/length を組み合わせた型は値型であるため、通常はスタックに保持されます。new を使用してヒープ上にその値の型を作成することをコンパイラが許可しない理由はわかりませんが、いつでも手動で作成できます。

import core.memory;
import std.stdio;

string* ptr;

void alloc()
{
    ptr = cast(string*)GC.malloc(string.sizeof);
    *ptr = "Hello World!";
}

void main()
{
    alloc();
    writefln("ptr=%s, ptr.ptr=%s, ptr.length=%s, *ptr=%s", ptr, ptr.ptr, ptr.length, *ptr);
}
于 2013-02-24T10:06:08.383 に答える
0

文字列は動的配列であるため、文字列の内容は既にヒープ上にあります。ただし、あなたの場合、可変性が必要なため、代わりに char 動的配列を使用することをお勧めします。

import std.stdio;

void main() {
  char[] a = null; // redundant as dynamic arrays are initialized to null
  writefln("a = \"%s\", a.ptr = %s", a, a.ptr); // prints: a = "", a.ptr = null
  a = "hello".dup; // dup is required because a is mutable
  writefln("a = \"%s\", a.ptr = %s", a, a.ptr); // prints: a = "hello", a.ptr = 7F3146469FF0
}

実際には配列の内容を保持するのではなく、そのスライスを保持することに注意してください。配列はランタイムによって処理され、ヒープに割り当てられます。この件に関する良い読み物は、この記事http://dlang.org/d-array-article.htmlです。

于 2013-02-22T07:00:00.167 に答える