V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
iqoo
V2EX  ›  程序员

C++ 类析构是按先进后出的顺序吗?

  •  
  •   iqoo · 2023-06-29 11:07:10 +08:00 · 1551 次点击
    这是一个创建于 546 天前的主题,其中的信息可能已经有所发展或是发生改变。

    函数中栈上定义的局部类,不会在函数外使用,有些是在块中定义的。每个类的析构顺序和定义顺序一定是正好相反吗?

    10 条回复    2023-06-29 16:59:21 +08:00
    newmlp
        1
    newmlp  
       2023-06-29 11:31:34 +08:00
    这是不是属于未定义行为,看编译器优化
    tool2d
        2
    tool2d  
       2023-06-29 11:38:54 +08:00
    "具体来说,构造函数中成员初始化列表的顺序决定了成员对象的构造顺序,而析构函数的调用顺序与构造函数相反。"

    网上查到的,理论上代码流程设计好,先析构后析构那个类,应该也没太大影响,不至于程序挂掉把。
    exch4nge
        3
    exch4nge  
       2023-06-29 11:43:39 +08:00
    语义上楼主说的对
    elechi
        4
    elechi  
       2023-06-29 13:54:23 +08:00
    是的
    flyqie
        5
    flyqie  
       2023-06-29 13:58:03 +08:00 via Android
    @newmlp #1

    这种应该不能算 ub 吧。。

    有些时候先析构函数之间也会有从属关系,要是 ub 的话那就太可怕了。。
    xylophone21
        6
    xylophone21  
       2023-06-29 14:15:13 +08:00
    https://isocpp.org/wiki/faq/dtors#order-dtors-for-locals

    这种问题来源比答案重要

    What’s the order that local objects are destructed?
    In reverse order of construction: First constructed, last destructed.

    In the following example, b’s destructor will be executed first, then a’s destructor:

    void userCode()
    {
    Fred a;
    Fred b;
    // ...
    }
    Rooger
        7
    Rooger  
       2023-06-29 14:26:29 +08:00
    C++ 类析构是按先进后出的顺序吗?
    函数中栈上定义的局部类,不会在函数外使用,有些是在块中定义的。每个类的析构顺序和定义顺序一定是正好相反吗?

    ChatGPT

    是的,你是对的。在 C++中,局部对象的生命周期遵循先进后出( LIFO )的顺序,这被称为栈式生命周期或者作用域生命周期。

    当一个局部对象在函数或者代码块中被创建时(例如通过声明或者初始化),它会在那个函数或者代码块的作用域内存在。当执行流程离开了那个作用域,局部对象就会被销毁。

    对于类类型的对象,销毁过程就是调用析构函数。这意味着,最后一个被创建(也就是最先进入作用域)的对象会最先被销毁(也就是最先离开作用域)。这正好与创建对象的顺序相反。

    例如:

    cpp
    Copy code
    {
    MyType a;
    {
    MyType b;
    } // b's destructor is called here
    } // a's destructor is called here

    在这个例子中,a 首先被创建,然后 b 被创建。但是 b 的析构函数会首先被调用,然后才是 a 的析构函数。
    justou
        8
    justou  
       2023-06-29 14:27:26 +08:00
    必须是那样, 利用 RAII 方式来保证一些动作得到执行
    void func(){
    auto socks_guard = wear_socks_guard(); // 构造时穿上袜子, 析构时脱掉袜子
    auto shoes_guard = wear_shoes_guard(); // 构造时穿上鞋, 析构时脱掉鞋

    // ....

    // 先脱鞋
    // 再脱袜子
    }
    leonshaw
        9
    leonshaw  
       2023-06-29 14:41:39 +08:00
    类 -> 对象?
    这不是 RAII 的基础么
    name1991
        10
    name1991  
       2023-06-29 16:59:21 +08:00
    ChatGPT 的答案能信吗?翻了下 c++ primer
    ChatGPT 说得对!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5066 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:15 · PVG 09:15 · LAX 17:15 · JFK 20:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.