String 为字符串分配内存

String 为字符串分配内存,string,d,String,D,在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`

在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

所以它显示的是同一个地址。为什么?

在D中,所有数组都是长度+指向数组值开头的指针。它们通常存储在堆栈上,而堆栈恰好是RAM

当您获取一个变量的地址(位于函数体中)时,您真正要做的是获取指向堆栈的指针

要获取数组值的地址,请使用
.ptr

因此,将
&str
替换为
str.ptr
,您将获得正确的输出。

您在代码中犯了一个简单错误:

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
索引和迭代不需要新的分配(当然)。信不信由你,但即使是追加有时也不会分配内存,因为在片的末尾可能还有未使用的内存(尽管通常会)

还有各种函数返回范围对象,这些对象在迭代时进行更改,从而避免分配。例如,代替
替换(a,“f”和“”),您可以执行类似于
过滤器的操作!(ch=>ch!='f')(a)并循环,除非您要求,否则不会分配新字符串


所以这比你想象的要微妙得多

我已经测试过了,它显示的是相同的地址。这是我最后一个编辑主题,`string*str\u ptr;str_ptr=&str;写(str_ptr)`和` writeln(str.ptr)`
&str
是指向数组的指针,
str.ptr
是指向内容的指针。