postblit构造函数是否仅与复制构造函数的来源不同?

时间:2014-03-15 19:51:50

标签: c++ d copy-constructor

如果我理解正确,D中的postblit构造函数从按位复制开始(总是),那么就有用户定义的主体。

但是当我查看postblit构造函数的主体时,它与C ++拷贝构造函数非常相似,唯一的区别在于C ++中的源是一些对象,当在D中是this(本身)时。

我说错了吗?

1 个答案:

答案 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方法。