2017-01-20 140 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( 「我」, 「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 

索引和迭代不需要新分配(當然)。相信與否,但即使追加有時也不會分配,因爲可能在片的末尾留下了尚未使用的內存(雖然通常會)。

還有各種函數會返回範圍對象,這些對象在您遍歷它們時執行更改,從而避免分配。例如,您可以使用filter!(ch => ch != 'f')(a);之類的代替replace(a, "f", "");的循環,除非您提出要求,否則不會分配新的字符串。

所以它比你想象的要多得多!

+0

'string * str_ptr; str_ptr = &str; writeln(str_ptr);''''和'writeln(str.ptr);' –

+0

'&str'是指向ARRAY的指針,'str.ptr'是指向CONTENTS的指針。 –

0

在D中,所有數組都是長度+指向數組值的開始的指針。這些通常存儲在棧上,而這恰好是RAM。

當你走一個變量的地址(它在函數體中)時,你真的在​​做的是獲得一個指向堆棧的指針。要獲取數組值的地址,請使用.ptr。 因此,用str.ptr代替&str,您將得到正確的輸出。

+0

我測試過了,它顯示的地址相同。我最後一個主題編輯。 –