2017-01-20 20 views
1

D文字列は、変更不可能な別名char[]のエイリアスです。したがって、メモリの割り当てによる文字列処理のすべての操作。私はそれを確認するために結束したが、文字列のシンボルを置き換えた後、私は同じアドレスを参照してください。文字列の割り当てメモリ

string str = "big"; 
writeln(&str); 
str.replace("i","a"); 
writeln(&str); 

出力:

> app.exe 
19FE10 
19FE10 

私が使用ptr試してみました:

string str = "big"; 
writeln(str.ptr); 
str.replace(`i`,`a`); 
writeln(str.ptr); 

をし、次の出力ました:

42E080 
42E080 

だから、それは同じアドレスを示していますが。どうして?

答えて

2

あなたはあなたのコード内での単純な誤り製:

str.replace( "i" は、 "A")を、

str.replace戻り行わ置換した新しい文字列が、それは実際には、既存の変数を置き換えるものではありません。変更を確認するにはstr = str.replace("i", "a");を試してください。

しかし、あなたはまた、割り当てについてあまりにも広く一般的な声明製:

メモリの割り当てと文字列処理上だから、すべての操作を。

これは間違いです。多くの操作で新しいメモリを割り当てる必要はありません。既存の文字列をスライスできるものは必要と新しいメモリを避け、そうします:

import std.string; 
import std.stdio; 

void main() { 
     string a = " foo "; 
     string b = a.strip(); 
     assert(b == "foo"); // whitespace stripped off... 

     writeln(a.ptr); 
     writeln(b.ptr); // but notice how close those ptrs are 
     assert(b.ptr == a.ptr + 2); // yes, b is a slice of a 
} 

replaceも代替はありませんが、実際には行われなかった場合は、元の文字列が返されます:

string a = " foo "; 
string b = a.replace("p", "a"); // there is no p to replace 
assert(a.ptr is b.ptr); // so same string returned 

インデックスと反復が新しい必要がありませんが割り当て(もちろん)。信じられないかもしれませんが、スライスの最後にまだ使われていないメモリが残っていることがあるので、時々追加されることもありません。

また、範囲のオブジェクトを返すさまざまな関数があります。これらの関数は、繰り返しを繰り返すときに変更を行い、割り当てを避けます。たとえば、replace(a, "f", "");の代わりに、filter!(ch => ch != 'f')(a);とループスルーのようなことがあります。ループスルーは、要求しない限り新しい文字列を割り当てません。

だから、あなたが思っているよりも微妙なニュアンスがあります。

+0

'string * str_ptr;の違いは何ですか? str_ptr = writeln(str_ptr); 'とwriteln(str.ptr); –

+0

'&str'はARRAYへのポインタで、 'str.ptr'はCONTENTへのポインタです。 –

0

すべての配列は長さ+配列値の先頭へのポインタです。これらは通常スタックに格納されます。スタックはまあまあRAMです。

実際に何をしているのか(関数本体にある)変数のアドレスを取得すると、スタックへのポインタが得られます。

アレイの値のアドレスを取得するには、.ptrを使用します。 &strstr.ptrに置き換えてください。正しい出力が得られます。

+0

私はそれをテストして、同じアドレスを表示しています。私の最後のトピック編集。 –