class Test1;
class Test2{ public: Test2(Test1* t1){
}
};
class Test1{ public: Test1():p(new Test2(this)){}//方法 1
//Test1(){p = new Test2(this);}//方法 2
Test2 *p;
};
使用方法 1 来构造,会不会有问题? 我的意思是当 new Test2(this)在执行时,能否确保传入的 this 已经是构造完毕的,比如说 Test2 的构造函数需要读取 Test1 对象的成员,假如这个 this 不是构造完毕的,其成员也是不确定的,那么 new 出来的 Test2 自然也有问题
1
sanjusss 2018-06-19 10:30:28 +08:00
需要看你的初始化顺序。Test2 访问在它之前已经初始化的 Test1 成员就没有问题。比较典型的是 Qt 里的 QObject。
|
2
paparika OP 两个方法效率上有差异吗
|
3
geelaw 2018-06-19 10:39:47 +08:00
成员初始化的顺序是成员在类 /结构中声明的顺序。
既可以选择 Test2 只访问 Test1 中已经初始化好的部分,也可以选择先把 p 设置为 nullptr,再交给 Test2 的构造函数。通常来说 p 是 nullptr 也不算是业务逻辑上初始化好的状态,所以 either way 你都需要 Test1、Test2 耦(内)合(聚)。 但如果 p 是 nullptr 的情况下 Test1 也算是业务逻辑上初始化好的状态,那么倾向于先初始化为这样,再变更为有一个 Test2 的情况。 |
4
gnaggnoyil 2018-06-19 10:41:18 +08:00
注意区分 allocate 和 construct 的区别.`new Test2(this)`在执行的时候`this`显然尚未被 construct,所以此时如果你在`Test2`的 constructor 里使用了 Test1 的成员那就相当于读取了一个未初始化的 object 那肯定是未定义行为……
不过具体到 LZ 这种写法反倒不需要关心这种问题:`Test2::Test2(Test1 *)`的函数体是在类内定义的所以此时`Test1`只有声明没有定义,因此`Test2::Test2(Test1 *)`的函数体内肯定没法使用`Test1`的成员,否则就是编译错误. |
5
paparika OP 嗯,我就是想确认下那个确实是未定义状态
|
6
seancheer 2018-06-19 11:05:34 +08:00
http://www.cs.technion.ac.il/users/yechiel/c++-faq/using-this-in-ctors.html
在构造函数 body 里面是没有问题的,这个时候成员已经被初始化 但是初始化列表中可能会访问到未初始化的成员。 另外,多说一句,构造方法中,父类使用子类 override 的 virtual 方法时,可能无法访问到子类 override 的方法。 |
7
sfqtsh 2018-06-19 11:21:45 +08:00 via Android
这样写有危险。
|
8
zh5e 2018-06-19 13:57:22 +08:00
1. 看构造函数有哪些逻辑,这个时候对象内存已经分配好了,成员变量没有相互引用来初始化就没关系
2. 构造函数执行过程中,this 指向的对象肯定没有构造完成 |