d复制构造器问题
原文
自DMD2.101.0
起,以下程序成功编译并运行完成:
struct S
{
this(ref S)
{
assert(0);
}
}
void main()
{
S[] a = [ S() ];
auto p = a.ptr;
// 直到重新分配,追加
while (a.ptr == p)
a ~= S(); // 无断定
}
重新分配
数组时,程序应该在运行时
断定,但是没有
,因为没有调用数组元素的复制构造器
.
如果更改复制构造器为postblit('this(this)')
,则程序期望的在运行时
断定.
另见影响了.dup
和.idup
的#20879问题
.
更清晰:
import std.typecons;
import std.sumtype;
import std.stdio;
import core.memory;
void fun(RefCounted!string foo) {
SumType!( RefCounted!(string) )[] foo_storage;
foo_storage ~= SumType!( RefCounted!(string) )(foo);
foo_storage ~= SumType!( RefCounted!(string) )(foo); // 再分配,但未复制
foo_storage = null;
}
void clobber()
{
int[1000] x = 0x123456;
}
void main(){
RefCounted!( string ) foo = RefCounted!( string )("哈哈");
fun(foo);
clobber();
GC.collect(); // 收集GC中已有项
writeln(foo);
}
这里:
1
.用sumtype
创建元素数组.
2
.数组
不能容纳第二个元素,所以重新分配.然而,没有调用SumType
的复制构造器
.因此'foo'
的引用计数为3
,但实际有4个引用(单元素
数组,双元素
数组,及栈
上的原始foo
).
3
.clobber
确保栈
不指向数组.
4
.GC.垃集
清理3个foo
元素,计数减少到0
并释放
.
5
.writeln
现在正在写垃圾
.在我系统上,它只是向屏幕
上喷出了随机
内存数字.
a~=S()
不应调用复制构造器
或postblit
,因为应该在数组
内原位
创建新追加的元素
.
问题在,重新分配
时复制
数组.正确调用了postblit
,但未正确调用复制构造器
.
struct S
{
this(this)
{
writeln("pblit");
}
}
void main()
{
S[] a = [ S() ];
auto p = a.ptr;
// 直到重新分配,追加
while (a.ptr == p)
{
writeln("loop");
a ~= S(); // 无断定
}
}
要么向TypeInfo
添加更多特殊成员
,要么修改勾挂
,以便可向运行时
解释如何调用
复制构造器.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现