2017-01-20 81 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

我测试过了,它显示的地址相同。我最后一个主题编辑。 –