关于 C++构造函数的一个疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
paparika
V2EX    C

关于 C++构造函数的一个疑问

  •  
  •   paparika 2018-06-19 10:22:54 +08:00 2553 次点击
    这是一个创建于 2761 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 自然也有问题

    8 条回复    2018-06-19 13:57:22 +08:00
    sanjusss
        1
    sanjusss  
       2018-06-19 10:30:28 +08:00
    需要看你的初始化顺序。Test2 访问在它之前已经初始化的 Test1 成员就没有问题。比较典型的是 Qt 里的 QObject。
    paparika
        2
    paparika  
    OP
       2018-06-19 10:36:21 +08:00
    两个方法效率上有差异吗
    geelaw
        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 的情况。
    gnaggnoyil
        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`的成员,否则就是编译错误.
    paparika
        5
    paparika  
    OP
       2018-06-19 10:45:59 +08:00
    嗯,我就是想确认下那个确实是未定义状态
    seancheer
        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 的方法。
    sfqtsh
        7
    sfqtsh  
       2018-06-19 11:21:45 +08:00 via Android
    这样写有危险。
    zh5e
        8
    zh5e  
       2018-06-19 13:57:22 +08:00
    1. 看构造函数有哪些逻辑,这个时候对象内存已经分配好了,成员变量没有相互引用来初始化就没关系
    2. 构造函数执行过程中,this 指向的对象肯定没有构造完成
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2662 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 02:07 PVG 10:07 LAX 18:07 JFK 21:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86