C++ 内存分配器作用域的设计

C++ 内存分配器作用域的设计,c++,design-patterns,memory,memory-management,scope,C++,Design Patterns,Memory,Memory Management,Scope,我一直在阅读关于内存管理的不同文章,为我希望我的体系结构如何工作做准备,我最担心的是如何在整个代码库中使用、创建和处理分配器。其中一个问题是,我的设计总是将分配器放在全局范围内,因为我没有一个典型的单例设计来包含分配器,它们没有真正的居住地。我希望避免使用globals,因为使用globals时会遇到一些典型的问题 这让我想到了这样的设计 void* operator new(size_t size, uint32_t type) { return gAllocator.Alloc(si

我一直在阅读关于内存管理的不同文章,为我希望我的体系结构如何工作做准备,我最担心的是如何在整个代码库中使用、创建和处理分配器。其中一个问题是,我的设计总是将分配器放在全局范围内,因为我没有一个典型的单例设计来包含分配器,它们没有真正的居住地。我希望避免使用globals,因为使用globals时会遇到一些典型的问题

这让我想到了这样的设计

void* operator new(size_t size, uint32_t type)
{
    return gAllocator.Alloc(size, type);
 }
这将导致在头文件中只包含新定义,在.cpp中包含声明。该.cpp文件将只有在.cpp文件中才有
gAllocator
(并且可以在除新调用之外的其他地方访问)


<>如果我的设计会是这样的, GalLoopeAs/C++ >仍然是一个全局变量,如果不是,那么它会考虑什么类型的变量?如果它在一个命名空间的范围内,如果

看起来一个简单的全局就是你想要的。应该是
内联
函数中的本地
静态
变量

class myAllocator {
public:
    static myAllocator &getDefaultInstance() {
        static myAllocator theInstance( parameters );
        return theInstance;
    }
};

这样,对象在第一次使用时就被初始化。如果使用典型的头声明+
.cpp
定义,则相对于其他全局变量的初始化顺序是未定义的,可能会产生不可预测的后果。(静态初始化顺序失败。)

为什么不为默认分配器实例创建一个典型的单例呢?Potatoswatter:单例通常是糟糕的设计,尤其是在游戏开发中(我的兴趣)。从技术上讲,如果您允许默认值之外的其他值,则它实际上不是单例。只需按照单例模式创建一个安全初始化的全局。@CharlesSalvia是的,它是。需要实现在初始化周围添加一个互斥体!全局对象比这种单例对象更简单、更健壮。@MaximYegorushkin check谷歌搜索(大多数结果指向堆栈溢出)要了解为什么更复杂的延迟初始化构造是首选的。如果您有一个名称空间范围对象更健壮的示例,请告诉我。@Potatostater:您使用Schwarz计数器强制全局变量的正确初始化顺序,就像std::cout/cin/clog在其他所有操作之前进行初始化一样。无需使用clumsy
myAllocator::getDefaultInstance()
syntax.@MaximyGorushkin一个Schwarz计数器只是手动实现这个习惯用法的隐式功能。但是您还必须手动添加线程安全性,并且(关键是)类需要围绕构造实现,这意味着构造函数必须为空…初始化委托会导致问题。如果要避免函数调用语法,可以通过返回全局实例实现隐式转换为
myAllocator
类型的对象。