在D中创建字符串而不分配内存?

Pet*_*der 8 string memory-management d immutability

是否有任何类型安全的方法来创建一个stringD,使用仅在运行时可用的信息,而不分配内存?

我可能想要做的一个简单示例:

void renderText(string text) { ... }

void renderScore(int score)
{
    char[16] text;
    int n = sprintf(text.ptr, "Score: %d", score);
    renderText(text[0..n]); // ERROR
}
Run Code Online (Sandbox Code Playgroud)

使用这个,你会得到一个错误,因为切片text不是不可变的,因此不是string(即immutable(char)[])

我只能想到三种解决方法:

  1. 将切片投射到string.它有效,但很难看.
  2. 使用切片分配新字符串.这有效,但我宁愿不必分配内存.
  3. 改变renderText采取const(char)[].这可以在这里工作,但是(a)它很难看,并且(b)Phobos中的许多功能都需要string,所以如果我想以相同的方式使用它们,那么这不起作用.

这些都不是特别好.我错过了什么吗?其他人如何解决这个问题?

Jon*_*vis 6

你有静态数组char.你想将它传递给一个需要的函数immutable(char)[].没有任何分配的唯一方法是施放.想一想.你想要的是一种类型,就像它是另一种类型.这就是演员所做的.你可以选择使用assumeUnique做到这一点,因为这不正是你要找的中投,但能否真正获得你什么是值得商榷的.它的主要目的是记录你演员正在做的事情是将被抛出的值视为immutable并且没有其他参考.看看你的例子,这基本上是正确的,因为它是函数中的最后一件事,但是你是否想要这样做一般取决于你.鉴于它是一个静态数组,冒着内存问题,如果你搞砸了,并将它传递给一个允许引用它泄漏的函数,我不确定这assumeUnique是最好的选择.但同样,这取决于你.

无论如何,如果你正在进行强制转换(无论是显式还是有assumeUnique),你需要确定你传递给它的函数不会泄漏对你传递给它的数据的引用.如果确实如此,那你就是在寻找麻烦.

当然,另一个解决方案是更改函数以便实现它const(char)[],但仍然存在泄漏对您传入的数据的引用的风险.因此,您仍然需要确定函数实际上是什么将要做.如果它pure,不返回const(char)[](或任何可能包含a的东西const(char)[]),并且它无法通过任何函数的其他参数泄漏,那么你是安全的,但如果其中任何一个不是真的,那么你我必须要小心.因此,最终,我相信所有使用const(char)[]而非铸造来string真正购买你的是你不需要施展.这还是更好的,因为它避免了搞砸演员阵容的风险(一般情况下,你可以避免施法时更好),但是你仍然需要担心逃避引用的所有事情.

当然,这也要求您能够更改功能以获得所需的签名.如果你不能这样做,那么你将不得不施展.我相信在这一点上,大多数 Phobos的基于字符串的函数已被更改,因此它们在字符串类型上被模板化.所以,现在使用Phobos这个问题应该不像以前那么严重.某些函数(特别是std.file中的函数)仍然需要进行模板化,但最终,Phobos中的函数需要string特别稀少,并且有充分的理由要求它.

然而,最终问题在于你试图将静态数组看作是一个动态数组,而D肯定会让你这样做,你这样做会冒一定的风险,你需要确定您正在使用的函数不会泄漏对您传递给它们的本地数据的任何引用.


Vla*_*eev 2

查看assumeUniquestd.exception乔纳森的回答。