DMD用复制构造函数移动结构

原文

struct std_string
{
    std_string* ptr;
    ulong[3] data;

    this (ulong data)
    {
        this.data[] = data;
        this.ptr = &this;//这里
    }//生命期不一致.

    this(const scope ref std_string from)
    {
        assert(&from is from.ptr);
        assert(this.ptr is null);
        this.ptr = &this;//这里
        this.data = from.data;
    }

    ~this ()
    {
        assert(this.ptr is &this);
    }

    alias opAssign = assign;

    ref std_string assign () (const auto ref std_string rhs)
    {//auto ref很可疑,按引用,按值?
        return this.assign2(rhs);
    }

    ref std_string assign2 (const ref std_string rhs) return
    {
        assert(rhs.ptr is &rhs);
        assert(this.ptr is null || this.ptr is &this);
        this.data = rhs.data;
        return this;
    }
}

void main ()
{
    std_string tmp = 42;
    assert(tmp.ptr is &tmp);
    tmp = std_string(42);
    assert(tmp.ptr is &tmp);
}

最初测试是查看DMD是否会使用复制构造器移动结构.上面的代码在LDCGDC下编译和运行良好,但在DMD下断定.
记住,D禁止成员内部指针.
如果添加@safe并用-preview=dip1000编译,会得到:
15行是:在构造器中this.ptr=&this;
22行是:在复制构造器中this.ptr=&this;

它不能仅用ref编译,所以简单删除auto ref会产生相同的结果(析构器中无限循环断定)
但是,按值传递表明另一个构造器和析构器调用,我怀疑问题出在"自动引用"上,复制构造器应该通过引用传递右值,对不?

不支持内部指针表明用户无法对接std::string,这对C++互操作是个巨大的打击.内部指针也是有复制构造器原因之一,不是吗?
调用者构造的值,我希望单个构造器调用.即,我期望:

tmp = std_string(42);
//和
auto someLValue = std_string(42);
tmp = someLValue;

只调用一次std_string构造器.
如果不使用autoref(按值传递),代码编译为上面两个片段,但在左值时就,会再调用一次构造器.
如果我使用普通的引用,不会编译第一个代码片(按右值传递).
注意,原始测试用例使用的是它只是接受右值的refin,所以我怀疑auto ref在此有问题(特别是考虑到LDCGDC正确,只有DMD有).

解释GDC行为.*因为*有个析构器(或postblit,复制构造器或其他使构不可复制的东西),则该类型是总是通过不可见引用隐式传递和返回的.
正确化简如下:

struct std_string
{
    std_string* ptr;
    ulong[3] data;

    this (ulong data)
    {
        this.data[] = data;
        this.ptr = &this;
    }

    ~this ()
    {
    }

 //即使前端决定从签名中删除`'ref'`,`GDC`和`LDC`强制转换`'autoref'`为`'ref'
    ref std_string opAssign()(const auto ref std_string rhs)
    {
        assert(rhs.ptr is &rhs);
        return this;
    }
}

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