V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
paparika
V2EX  ›  C

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

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

    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   ·   实用小工具   ·   2788 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:45 · PVG 21:45 · LAX 05:45 · JFK 08:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.