天天看点

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​

​​是否会使用​

​复制构造器​

​​移动结构.上面的代码在​

​LDC​

​​和​

​GDC​

​​下编译和运行良好,但在​

​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;      
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);
}