重载运算符删除而不重载new时正确的行为是什么? gcc和clang不同

时间:2019-12-17 11:29:30

标签: c++ gcc clang operator-overloading overload-resolution

以下代码与 clang (x86_64-pc-linux-gnu上的版本5.0.0-3〜16.04.1)和 gcc (9.2.0 )。

void operator delete(void* ptr) noexcept {
    std::cout << "overloaded delete" << std::endl;
    free(ptr);
}

int main() {
    int* pint = new int;
    delete pint; // clang doesn't go through overloaded operator delete, gcc does
}

gcc 通过重载的operator delete,而 clang 则避免使用{{1 }}。

(添加重载global delete时,两个编译器都同意并通过两个重载版本)。

代码:http://coliru.stacked-crooked.com/a/0903bd53a8c04a9b

1 个答案:

答案 0 :(得分:1)

允许编译器使用new优化分配,并完全忽略对全局可替换operator newoperator delete的调用,即使它们有副作用,请参见{{3 }}和[expr.new]/10的C ++ 17标准草案。


如果不使用-O2标志进行编译,则会看到同时打印了编译器和gcc主干的消息,并且忽略了启用了优化的分配。


如果编译器未删除分配/取消分配函数调用,则我认为您的operator delete具有未定义的行为,因为您无法保证所传递的指针是由{{1}分配的},并在其上调用malloc会导致未定义的行为。

您需要始终同时替换freeoperator new