如果我理解正确,D中的postblit构造函数从按位复制开始(总是),那么就有用户定义的主体。
但是当我查看postblit构造函数的主体时,它与C ++拷贝构造函数非常相似,唯一的区别在于C ++中的源是一些对象,当在D中是this
(本身)时。
我说错了吗?
答案 0 :(得分:3)
a = b;
(iff a和b都是相同类型,结构)转换为:
memcpy(&a, &b, b.sizeof); // bitwise copy
a.__postblit(); // call the postblit on the destination only (iff this(this) is defined on the type!)
因此,您不必在postblit中显式分配任何变量(它们都是自动复制的),也不能用它来实现移动语义(您无权访问源代码)。
我经常使用postblit的地方是当struct是指向另一个对象的指针时,所以我可以增加refcount:
struct S {
SomeObject* wrapped;
this(this) { if(wrapped) wrapped.addReference(); }
~this() { if(wrapped) wrapped.releaseReference(); }
}
这仅适用于引用,否则您将增加变量的副本!
你可以(但不应该)也用它来执行深层复制:
struct S {
string content;
this(this) { content = content.idup; }
}
但这实际上是一个坏主意,因为结构分配应该在D中普遍便宜,而深拷贝并不便宜。反正通常也没有必要,因为垃圾收集器处理像双重空闲的情况,你可能想要在C ++中使用它。
我在D中经常使用它的另一种情况实际上是禁用它:
struct S {
@disable this(this);
}
S a, b;
a = b; // compile error, b is not copyable
这与完全没有实现postblit不同,这使得你可以自动执行memcpy。这使得赋值成为一个彻头彻尾的编译错误,您可以使用它将用户转向另一个方法,例如移动语义:
struct S {
int* cool;
@disable this(this);
S release() { auto n = cool; cool = null; return S(cool); }
}
由于a = b被禁止,我们现在可以强制用户在想要重新分配它时使用.release方法。