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

时间:2011-10-01 10:39:04

标签: string memory-management immutability d

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

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

void renderText(string text) { ... }

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

使用此功能,您会收到错误,因为text的切片不是不可变的,因此不是string(即immutable(char)[]

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

  1. 将切片投射到string。它有效,但很难看。
  2. 使用切片分配新字符串。这有效,但我宁愿不必分配内存。
  3. 更改renderText以获取const(char)[]。这可以在这里工作,但是(a)它很难看,而且(b)Phobos中的许多函数需要string,所以如果我想以相同的方式使用它们,那么这不起作用。
  4. 这些都不是特别好。我错过了什么吗?其他人如何解决这个问题?

4 个答案:

答案 0 :(得分:6)

您拥有char的静态数组。您希望将其传递给带immutable(char)[]的函数。不使用任何分配的唯一方法是强制转换。想一想。你想要的是一种类型,就像它是另一种类型。这就是演员所做的。您可以选择使用assumeUnique来执行此操作,因为这确实是您正在寻找的演员阵容,但这是否真的让您获得任何东西都是值得商榷的。它的主要目的是记录你演员正在做的是将正在演绎的值视为immutable,并且没有其他引用。看看你的例子,这基本上是正确的,因为它是函数中的最后一件事,但是你是否想要这样做一般取决于你。鉴于它是一个静态数组,冒着内存问题,如果你搞砸了,你把它传递给一个允许引用泄漏的函数,我不确定assumeUnique是最好的选择。但同样,这取决于你。

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

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

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

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

答案 1 :(得分:2)

从std.exception中查看 assumeUnique Jonathan的回答。

答案 2 :(得分:0)

不,您不能 创建 字符串 ,无需分配 。您的意思是 访问 吗?为避免分配,您必须使用切片或指针来访问先前创建的字符串。虽然不确定是否可以使用,但它可能会或可能不会为新字符串分配新的内存空间。

答案 3 :(得分:0)

解决这个问题的一种方法是将可变字符复制到一个新的不可变版本然后切片:

void renderScore(int score)
{
    char[16] text;
    int n = sprintf(text.ptr, "Score: %d", score);
    immutable(char)[16] itext = text;
    renderText(itext[0..n]);
}

然而:

  1. 由于存在错误,DMD目前不允许这样做。
  2. 您正在创建一个不必要的副本(优于GC分配,但仍然不是很好)。