d传递32位数据到S
原文
从数据源传递32位数据,构造器,一切都很好,但我不能用foo()
方便函数保持对象活着
.
示例:
import std.stdio;
struct S
{
char[size] bytes;
alias toString this;
string toString() const
{
scope res = [ cast(string) bytes ];
return res[0];
}
}
string foo(char[size] bytes)
{
scope res = S(bytes);
return res.toString(); // 问题在此.
}
enum size = 4;
void main()
{
char[size] text = "abcd".dup;
auto m = S(text); // 测试正常
assert(m == text);
foo(text).writefln!"(%s)"; //(?)
}
//
string foo(char[size] bytes)
{
scope res = new S(bytes);
return res.toString(); // 问题在此
}
还有:我用new
符号构造S
时就可以了.
char[size] bytes;
alias toString this;
string toString() const
{
scope res = [ cast(string) bytes ];
return res[0];
}
这段代码
是完全错误的.你错误地转换可变
并限制了生命期
数据为串
,然后返回它.不必用域 res
;该代码等价于return cast(string)bytes;
,编译器为你切片,取指针,然后用新类型
切片返回.
所以这是返回局部变量
指针,一旦调用
它的函数返回
了,该变量就没了.
string foo(char[size] bytes)
{
scope res = S(bytes);
return res.toString(); // 问题在此
}
S
中的那些字节
在该foo
函数的栈中.你返回它们的指针
,然后foo
函数返回
,则栈上的那些字节
不再存在(重用
内存,但在概念上是相同的),但你保存
了引用.
auto m = S(text); // test ok
assert(m == text);
这只是有效,因为m
在断定点
仍然存在,一旦有另一个
函数,栈内存
就消失了.
你或者用.idup
字节,或让你的toString
用void delegate(in char[])sink
,然后传递
字节给sink
,并转换为char[]
.
scope res = new S(bytes);
scope
关键字表明,你保证不会让该变量的引用
逃逸该域
.你的toString
会这样做,因此编译器
可能会优化掉"new"
;这里域和新
关键字相互抵消,给你留下同样的问题.
我用new
符号构造
S时就可以了!
仍然是错误
代码,但可在此工作,因为字节此时是GC
管理而不是栈临时
,所以你仍然转换为不变
,但至少它不是释放后使用
.
我相信当前推荐
方法[1]
不是使用闭包接收器
,而是使toString
成为接受输出区间
的模板:
import std.range;
void toString(Sink)(ref Sink sink)
if (isOutputRange!(Sink, char))
{
put(sink, cast(char[]) bytes);
}
我试用outputrange
但没有成功.但我是这样实现的,并且可完美地返回活串
.
import std.format, std.stdio;
struct S(int len)
{
char[len] bytes;
void toString(void delegate(const(char)[]) sink) const
{
auto res = cast(char[]) bytes;
typeid(res).writeln(" toString()=>");
sink.formattedWrite("%s", res);
}
}
char[] foo(char[9] bytes)
{
auto res = cast(char[]) format("%s", S!9(bytes));
scope(exit)
typeid(res).writeln(" foo()=>");
return res;
}
void main()
{
char[9] text = " Hello D".dup;
auto test = S!9(text);
test.writeln; // ok
foo(text).writeln; // ok
}
/* Output:
char[] toString()=>
Hello D
char[] toString()=>
char[] foo()=>
Hello D
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现