运算符new的执行顺序和构造函数的参数

Posted

技术标签:

【中文标题】运算符new的执行顺序和构造函数的参数【英文标题】:Execution order of operator new and argument of constructor 【发布时间】:2020-04-14 13:53:53 【问题描述】:

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 谢谢你的建议。我把两者混在一起了。 【参考方案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 编译会得到相同的结果。

【讨论】:

以上是关于运算符new的执行顺序和构造函数的参数的主要内容,如果未能解决你的问题,请参考以下文章

java类创建时里面成员执行的先后顺序

构造函数顺序

类加载时执行顺序

第21课 - 对象的构造顺序

关于构造函数及参数执行顺序说明(c#)

java父子类的初始化顺序--个人总结