You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++标准6.7.3.5中“依赖析构副作用”含义的技术问询

对C++20标准中析构函数未调用相关未定义行为的解读困惑

程序可通过重用对象占用的存储、显式调用对象的析构函数或伪析构函数(7.5.4.4)来终止任意对象的生存期。对于类类型的对象,程序无需在重用或释放其占用的存储前显式调用析构函数;但如果未显式调用析构函数,也未使用delete表达式(7.6.2.9)释放存储,则析构函数不会被隐式调用,任何依赖该析构函数产生的副作用的程序都存在未定义行为(undefined behaviour)。
引用自ISO/IEC 14882:2020(E)(C++20标准)

我对上述段落最后一句话存在困惑,它是典型的“若X则Y”结构,Y是严重的未定义行为,但X的含义不明确。目前我有两种合理解读:

  • 解读1:缺少析构函数调用时,可观察副作用不应发生变化(类似“as-if”规则的思路)
  • 解读2:如果其他代码需要依赖“析构函数被调用”的假设来保证程序良构,那么不调用析构函数会导致未定义行为

针对解读1的验证分析

编写了测试代码,编译选项为-std=c++20 -O3 -fsanitize=undefined,分别在常量求值上下文和运行时执行测试逻辑:

  • 在常量求值函数f()中,创建对象s并调用print_buffered()标记需要打印,随后通过std::construct_at(&s)终止原对象生存期并构造新对象,全程未调用原对象的析构函数
  • 原对象的析构函数若被执行,会产生向标准输出打印内容的可观察副作用
  • 通过static_assert(f() == 12)强制常量求值上下文执行f(),同时在main()中执行相同逻辑用于检测未定义行为

测试结果:static_assert未触发,clang和gcc均未将该情况判定为未定义行为;运行时执行时,未定义行为 sanitizer也未捕获问题。这说明要么该情况确实不属于未定义行为,要么编译器存在问题;若为前者,则可作为反对解读1的证据。此外,这种情况本应可被诊断,编译器可尝试分析析构函数是否存在可观察副作用。

针对解读2的分析

该解读在某种意义上显得冗余,但并非严重问题。我目前倾向于第二种解读,但不确定是否正确。我未在标准中找到“depends”的明确定义,日常语境中我不认为示例程序依赖析构副作用,我认为该词适用于“不调用析构函数会破坏程序正确性关键不变量”的场景。

测试代码

#include <new>
#include <iostream>

struct S {
private:
    bool m_print;
public:
    constexpr S() : m_print(false){}

    S(const S&) = delete;
    S(S&&) = delete;

    S& operator=(const S&) = delete;
    S& operator=(S&&) = delete;

    constexpr void print_buffered(){m_print = true;}

    constexpr ~S(){
        if (m_print) std::cout << "HELLO WORLD" << std::endl;
    }
};

constexpr int f(){
    S s;
    s.print_buffered();
    std::construct_at(&s); // placement new not usable in constant-evaluated contexts :'
    return 12;
}

static_assert(f() == 12);

int main(){
    std::cout << "Hi\n";
    S s;
    s.print_buffered();
    new (&s) S; // this ends lifetime of object and starts lifetime of new object
    std::construct_at(&s); // ^ same
}

内容的提问来源于stack exchange,提问作者Ivan Lazaric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:47:54