我想重新定义 new 和 delete 运算符,以便在包含多个翻译单元的 C++ 项目中使用自定义分配器。以下是 memops.hpp 文件中的重新定义:
#pragma once
#include "../lib/mem.h"
void* operator new(size_t size) {
return __mem_alloc(size);
}
void operator delete(void *ptr) {
__mem_free(ptr);
}
void* operator new[](size_t size) {
return __mem_alloc(size);
}
void operator delete[](void *ptr) {
__mem_free(ptr);
}
我的问题是,这个头文件应该包含在哪里?这有什么区别吗?这个替代定义是否适用于项目中所有地方?
我找到了这篇文章https://www.ibm.com/docs/en/i/7.4?topic=heap-overloading-new-delete-operator,但最后一段让我感到困惑。
在哪里包含带有自定义分配器的memops.hpp很重要,这取决于您如何重新定义全局new和delete运算符。
在 C++ 中,当您在翻译单元中定义全局运算符 new /运算符 delete时,它们将成为整个程序的全局运算符 - 当且仅当它们是链接到最终可执行文件中的运算符。
但是,您应该记住,如果将此定义放在标题中并将其包含在多个 .cpp 文件中,您将获得多个定义 - 违反一个定义规则(ODR)。
此外,我建议您仅在头文件中声明方法,并在单个 .cpp 文件中编写实现。
因此,memops.hpp 将如下所示:
和 memops.cpp:
这样,全局重载只定义一次,因此链接器会将它们应用于程序中所有new和delete的使用- 只要没有其他翻译单元提供不同的定义。
关于文章最后一段,我认为这主要适用于共享库的情况。在这种情况下,除非显式链接或包含全局符号,否则全局符号可能不会传播到其他模块。在标准 C++ 项目中,尤其是在静态链接的情况下,在一个翻译单元中定义重载就足够了。