d中不变与数组

原文
rumbu:想理解编译器行为:

struct SimpleStruct { int x;}
struct ComplexStruct { int[] x; }

void main()
{
    SimpleStruct[] buf1;
    immutable(SimpleStruct)[] ibuf1;
    buf1[0 .. 10] = ibuf1[0 .. 10];
    //工作

    ComplexStruct[] buf2;
    immutable(ComplexStruct)[] ibuf2;

    buf2[0 .. 10] = ibuf2[0 .. 10];
    //错误,不能隐式转换`immutable(ComplexStruct)[]`类型的`ibuf2[0..10]`到`ComplexStruct[]`
}

WebFreak001:
规范说:
可变间接引用值(包括不含可变间接引用字段的构)可在mutable,const,immutable,const shared,inoutinout shared间隐式转换.
因此第一个结构可在可变/不变/常间隐式转换,因为它不包含(可变数组/指针/引用)的可变间接.
Stanislav Blinov:因为is(typeof(immutable(ComplexStruct).x)==immutable(int[])).不能绑定不变数组到可变数组.需要深复制,即复制构造器.
Steven Schveighoffer:
第一例,有个包含整数的简单结构.复制该构时,无间接(指针),即允许调整可变性:

immutable s = SimpleStruct(5);
SimpleStruct s2 = s; // 好,复制所有

第二例,int[]包含指针.如果复制它,就不能改变类型可变性,因为它有到不变数据可变指针:

immutable s = ComplexStruct([5]);
ComplexStruct s2 = s; // 错误,不能隐式转换,有个`间接`.

为什么?假设允许它,s2是可变的,即s2.x是可变的.现在可这样:

s2.x[0] = 6;

突然之间,可修改不变数据了!这是禁止的,因而不能复制结构.

Stanislav Blinov:
不完全是.这里可能有个真正错误:

struct S
{
    int[] x;

    // 没用它,后复制也不行
    this(ref return scope inout S other)
    {
        x = other.x.dup;
    }

    void opAssign(ref return scope inout S other)
    {
        x = other.x.dup;
    }
}

void main()
{
    immutable(S)[] src = [S([1, 2]), S([3, 4])];

    auto dst = new S[src.length];
    //dst[0 .. $] = src[0 .. $];
    //即使定义了`opAssign`,也不编译
    //这可以:
    foreach (i, ref it; dst)
        it = src[i];
}

规范:
根据规范,(在检查重叠后),分配切片应与foreach循环一样.但没有,只是尝试隐式转换,但失败了.

现在,因为有了复制构造器,切片赋值应该尝试复制赋值元素(即无opAssign时,先试复制构造器).
Steven Schveighoffer:
我同意在此切片赋值复制构造器应工作.我认为目前是它仍依赖memcpy+后复制,(数组运行时多数还是神奇函数).
后复制不管用,因为它先按原样复制数据,即仍然是不变的,只有在后复制之后才是可变的.
注意,这不是构造,它应该用opAssign.再说一遍,可能是运行时用了memcpy+后复制.如果无报告,应该是这样.
简单证明这是漏洞:

immutable (ComplexStruct)[] arr;
ComplexStruct[] arr2;

arr2[0] = arr[0]; // ok
arr2[] = arr[]; // 错误

如果可复制元素,则应可复制所有元素.

posted @   zjh6  阅读(15)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示