关于函数属性@safe
,pure
和nothrow
以及父函数的编译时和运行时性能构造字符串的首选方法是什么?
我们应该使用,例如
format("Variable x=%s should equal %s", x, x_)
或
"Variable x=" ~to!string(x)~ " should equal " ~to!string(x_)
我认为format
版本更容易看到,但在其他方面它更好吗?
编译时可能会有轻微的性能损失,因为格式字符串及其参数必须是CTFEed吗?
答案 0 :(得分:1)
第一个版本通常更好。在编译性能方面没有显着差异(如果有的话,forrmat不是ctfe),而format()实际上应该表现得更好。
二进制“foo”〜“bar”的成本往往非常昂贵,因为它会分配垃圾收集器必须清理的中间结果。
在我所拥有的dmd版本中,这两个版本实际上都没有编译为安全,而不是纯粹。我认为他们用phobos git解决了这个问题,但我不确定。无论如何,现在既不实际工作,除了实现自己的功能之外,没有简单的解决方法,除非它只是用于调试。
在调试语句中放宽了纯粹的要求,你可以在@system中包含非@安全函数,并在try / catch中抛出函数来获取这些属性。
因此,这实际上会编译:
// trusted gets around safe
@trusted pure nothrow string myformat(T...)(in string fmt, in T t) {
import std.string;
// debug gets around the pure requirement
debug try // try gets around nothrow
return format(fmt, t);
catch(Exception e) { }
return null;
}
@safe nothrow pure void main() {
import std.conv;
string s = myformat("test %s", 10);
assert(0, s); // the assert message shows up
}
使用-debug开关编译:dmd test.d -debug
所以不是一个很好的解决方案,但是直到具有正确属性的phobos函数被释放,或者如果你想编写自己的format()或to()函数(实际上并不那么难),你可以做int to string in < 10行)可能是你能做的最好的。
答案 1 :(得分:0)
正如接受的答案所说,更喜欢format!
,并且更喜欢将format-string作为模板参数传递:
#!/usr/bin/env rdmd
module test;
import std.format; // or std.string, which publicly imports std.format
import std.stdio;
void main()
{
writeln(format("%s%s","run-time error 'Orphan format specifier'"));
writeln(format!"%s%s"("compile-time error 'Orphan format specifier'"));
}
自DMD 2.074.0于2017年4月发布以来可用。