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;
编译器正确的拒绝了.
当然,它只是因为编译器插入的析构器忽略了常,这有点可疑,但这是无害的.
安全引用计数
浙公网安备 33010602011771号