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

GCC与Clang未遵循new表达式中分配函数的重载解析规则?

GCC/Clang拒绝匹配带align_val_t的operator new的原因分析

先看你的代码示例:

#include <iostream>

struct A{
    void* operator new(std::size_t N, std::align_val_t){  // #1
        return malloc(sizeof(char)* N);
    }
};
int main(){
    auto ptr =  new A;  // #2
}

GCC和Clang的报错信息如下:

<source>:9:17: error: no matching function for call to 'operator new'
    auto ptr =  new A;
                ^
<source>:4:11: note: candidate function not viable: requires 2 arguments, but 1 was provided
    void* operator new(std::size_t N, std::align_val_t){
          ^
1 error generated.

你对C++标准[expr.new] p19条款的理解方向是对的,但忽略了两个关键细节:

1. 类成员函数对全局同名函数的隐藏规则

当你在类中定义了任何版本的operator new成员函数时,C++的名称查找规则会直接隐藏全局作用域中所有同名的operator new函数——不管全局函数的参数签名是否和成员函数一致。

所以第一次重载解析时,编译器只会在A的作用域内查找匹配operator new(std::size_t)的函数,但A中只有带两个参数的版本,自然匹配失败。

2. 编译器对二次重载解析规则的实现缺陷

根据标准[expr.new] p19的规定,第一次解析失败后,对于非扩展对齐的对象,应该自动添加std::align_val_t(alignof(A))参数,再次进行重载解析——此时你的operator new(std::size_t, std::align_val_t)完全匹配新的参数列表。

但目前GCC和Clang并没有正确实现这一二次解析逻辑,直接在第一次匹配失败后就抛出错误,这属于编译器的实现缺陷。

验证与绕过方法

如果给A添加扩展对齐(即对齐要求大于平台默认的__STDCPP_DEFAULT_NEW_ALIGNMENT__,通常是8或16字节),比如:

struct alignas(32) A{
    void* operator new(std::size_t N, std::align_val_t){
        return malloc(sizeof(char)* N);
    }
};

此时编译器会在第一次组装参数列表时就包含align_val_t参数,代码可以正常编译——这也侧面证明标准规则本身是正确的,只是编译器对非扩展对齐场景的二次解析逻辑未实现。

你也可以通过显式引入全局operator new临时绕过,但这不符合你的原本意图:

struct A{
    using ::operator new; // 引入全局operator new
    void* operator new(std::size_t N, std::align_val_t){
        return malloc(sizeof(char)* N);
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 22:10:49