d放松不变4
如果@system
和__metadata
是单独的注解,你会得到:@system
规则__metadata
规则.
变量是@system
原因很多,因为它只是收集
了不安全的来源
.__metadata
是考虑添加
到语言
中的新的此类源
.
因为DIP1035
并不改变变量类型
.
编译器
仍跟踪所有这些
,并使其作为注解部分,来更易理解.
新手在很长一段时间
内都不必学习__metadata
或@system
变量.可能某时遇到@system
变量,最后,更少数D程序员
需要非常关注__metadata
规则.
这里,"不安全
类型"在DIP
中详细说明了,有特定意思.即使是不安全
类型,一般可从@safe
代码中使用.
我同意实际工作生命期
语义应比在不变
结构中隐藏引用计数
有更高优先级
.
:不变与rc
.
我认为该问题
的方法应归结为以下之一:
-接受不变
表明不变,仅在强制执行
该从基于UB(未定义行为)
的规范中继承有效编译器优化
的限制
真正有意义就使用它.禁止使用不变
的RC
.不变
总是可放在只读
内存中,这是CTFE
访问不变值的简单故事.
-接受"不变
"结构中有专门
用于低级目的
的可变
部分,区分"不变
"和"共享 不变
",明确指定基于非确定性语义
的有效
编译器优化.不变RC
是个问题
.根据特定类型
决定是否放"不变
"值进只读
内存,CTFE
访问不变
值更复杂.
这不是应用限定符
到用户定义类型
的唯一问题.内置切片
和指针类型
,相对用户定义类型
,与限定符
有神奇交互
作用.
:带@系统
字段的聚集
是不安全
类型.
目的是防止
在@safe
代码中,对@system
字段类型的空初化
等.仍可在不用@trusted
就访问结构
的非@system
字段.
“不安全
类型”,不表明不能在@safe
代码中使用
它.如,指针
是不安全
类型,可在@safe
代码中安全
使用指针
."不安全
类型"即,在@safe
代码中,仅在编译器
知道不会导致损坏内存
时使用
它.
是的.
但如果编译器允许RC
变为常
,并禁止RC
,那就糟了.
那就是我上面的测试代码干的,它会尽量避免用const
.这是解决更大问题
的方法.
不变
与生命期
语义无关.只是说不会修改这段内存
.无论如何,真正问题在于常
.可变和不变
都自动转为常
.
:这似乎是为了拥有适当的安全可变
的RC
结构,需要纠正
的特例和错误
.如果需要,应可禁止隐式
转换为常 构
.
对的.只需编写RC!T
的复制
构造器来请求可变源和目标
对象,编译器将拒绝
复制const(RC!T)
.(当然,也可常 引用
.)
:关于使用常 rc
,我认为如果禁止取有效负载
的地址或子元素
,可受限
访问负载
.也许不是从rc
结构返回有效负载
,而是包装到从负载访问字段
时避免取地址
的包装器中.
可传递负载
的"域引用
"给回调
来限制访问
,如下:
这里
import std;
void main()
{
int j = 2;
int k = 3;
const r3 = Counted!int(&j);
const(Counted!int) r4 = Counted!int(&k);
}
@safe struct Counted(T)
{
private T* subject;
private size_t* counter;
this(T* subject)
{
this.counter = new size_t;
this.subject = subject;
*this.counter = 1;
}
this(ref T subject) const @disable;
this(T* subject) const @disable;
this(ref Counted!T counted)
{
this.subject = counted.subject;
this.counter = counted.counter;
++(*this.counter);
}
this(ref Counted!(const T) counted) const @disable;
this(ref const Counted!T counted) const @disable;
this(ref Counted!T counted) const @disable;
this(this) @disable;
~this()
{
(*this.counter)--;
if ((*this.counter) == 0)
{
writeln("释放:",*this.subject);
this.counter = null;
}
}
// ~this() const @disable; 很明显另一个漏洞或未图表区域.
void opAssign(ref Counted!T counted)
{
--(*this.counter);
this.subject = counted.subject;
this.counter = counted.counter;
++(*this.counter);
}
void opAssign(Counted!T counted)
{
this = counted;
}
void opAssign(ref const(Counted!T) counted) const @disable;
void opAssign(const(Counted!T) counted) const @disable;
void opAssign(Counted!(const T) counted) const @disable;
void opAssign(ref Counted!(const T) counted) const @disable;
void opAssign(ref Counted!T counted) const @disable;
void opAssign(Counted!T counted) const @disable;
void opCast(T)() @disable;
}
没问题.创建且销毁了Counted!int
的两个实例.没有泄露或悬空
引用.如果复制构造附加实例
,如
auto r5 = r4;
编译器正确的拒绝了.
当然,它只是因为编译器插入的析构器
忽略了常
,这有点可疑,但这是无害
的.
安全引用计数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现