d中复制构造器与构造器
原文
vit:为什么这段代码无法编译?
struct Foo(T){
this(Rhs, this This)(scope Rhs rhs){
}
this(ref scope typeof(this) rhs){
}
}
struct Bar{
Foo!int foo;
}
void main(){
}
//错误:分段错误(已转储核心)
RazvanN:
问题是编译器会尝试为Bar生成大致如下所示的inout复制构造器:
this(ref scope inout(Bar) p) inout
{
this.foo = p;
}
变形理念是是尽量调用Foo对象的复制构造器.问题是复制构造器与(__ctor)构造器符号相同,因此变形this.foo=p为foo.__ctor(p).
因为实例和参数都是inout,不能调用Foo的复制构造器,因而调用模板构造器.生成this(scope inout(Foo))inout;样的构造器的模板实例.它是右值构造器.不是有效代码;如果这样:
struct Foo(T){
//this(Rhs, this This)(scope Rhs rhs){}
this(scope inout(Foo!int) rhs) inout {}
this(ref scope typeof(this) rhs){
}
}
将收到不能同时定义右值和复制构造器的错误消息.但,由于是模板化构造器,在实例化构造器前,编译器不能发出错误.有2个可能修复方法:
(1)重命名复制构造器为__cpCtor,这样不会与普通构造器重载集冲突
(2)实例化模板构造器时,可检查是否是右值构造器,并在存在复制构造器时发出错误.
实现复制构造器时,我认为(1)更好,但d作者坚持要他们有相同名称.所以,(2)是要走的路.
Tejas:那为什么我的修改成功了?
struct Foo(T){
this(Rhs, this This)(scope Rhs rhs){
}
this(scope Foo!(T)* rhs){
//用 Foo!T替换typeof(this),用指针替换引用.
//保留typeof(this),依然工作
}
}
struct Bar{
Foo!int foo;
}
void main(){
import std.stdio:writeln;
Bar bar = Bar();
auto BAR = new Bar();
writeln(bar, "\t", BAR, "\t", *BAR);
}
RazvanN:
是的,要通过传递ref参数来显式定义复制构造器.因为你期望显式指针,编译器不按复制构造器对待,因此不会为Bar生成复制构造器.
在此
vit:现在如下工作了:
struct Foo(T){
this(Rhs, this This)(auto ref scope Rhs rhs)
if(__traits(isRef, rhs) == false){
}
this(ref scope typeof(this) rhs){
}
}
struct Bar{
Foo!int foo;
}
void main(){
}
在本地运行它时,它是编译时段错误.把右值构造器误当作复制构造器时,编译器尝试变形调用它,但还要复制传递参数,因此它进一步变形为另一个调用右值构造器.因此导致无限递归,从而栈溢出和段错误.
浙公网安备 33010602011771号