【问题标题】:Execution order of operator new and argument of constructor运算符new的执行顺序和构造函数的参数
【发布时间】:2023-03-29 20:00:01
【问题描述】:

C++ 规范是否在new C(A()) 中指定了operator new 的顺序和A 的构造函数。
g++ 让顺序为 A() -> new -> C(),但 clang++ 让它为 new -> A() -> C()
差异是由未指定的行为引起的吗?

g++ :7.4.0 铿锵++:10.0.0

#include <iostream>
#include <cstdlib>

struct A {
    A() {
        std::cout << "call A()\n";
    }
};

struct C {
    C(A) {
        std::cout << "call S()\n";
    }

    void *operator new(size_t s) {
        std::cout << "call new()\n";
        return malloc(s);
    }
};

int main() {
    void *p = new C(A());
}

【问题讨论】:

  • 您是使用 C++17、C++14 还是之前的版本构建?
  • 两个注意事项:你用“C”标记了这个,这清楚地表明你没有阅读该标记的描述。别。现在,您询问“未定义的行为”(UB)。这是 C++ 标准使用的一个术语,用于标记任何事情都可能发生并且应该避免的事情。还有“未指定的行为”,这可能更接近您所追求的,因为代码在技术上很好并且不会导致 UB。
  • @Ulrich Eckhardt 谢谢你的建议。我把两者混在一起了。

标签: c++ language-lawyer c++17 order-of-execution


【解决方案1】:

Clang 是正确的。从 C++17 开始,执行顺序得到保证。 [expr.new]/19

分配函数的调用在new-initializer中的表达式计算之前排序。

operator new(分配函数)应该首先被调用,然后是 new-initializer 中表达式的求值(即A())。

在 C++17 之前,不保证顺序。 [expr.new]/18 (C++14)

分配函数的调用相对于new-initializer 中表达式的求值是不确定的。


gcc 似乎不符合 C++17(及更高版本);使用gcc10 in C++2a mode 编译会得到相同的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-22
    • 2010-12-25
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    相关资源
    最近更新 更多