无动态内存分配的C++类间数据共享优化方案求助
解决方案与重构思路
一、无动态内存分配场景的优化方案
1. 全局服务定位器(Service Locator)
创建全局静态容器类,统一持有所有对象的引用,在builder.cpp中完成初始化。业务类通过该容器获取所需对象的引用,避免构造函数参数爆炸,同时解决循环依赖问题。
示例代码:
// ServiceLocator.h #pragma once class A; class B; class C; class D; class ServiceLocator { public: static void init(A& a, B& b, C& c, D& d) { s_a = &a; s_b = &b; s_c = &c; s_d = &d; } static A& getA() { return *s_a; } static B& getB() { return *s_b; } static C& getC() { return *s_c; } static D& getD() { return *s_d; } private: static A* s_a; static B* s_b; static C* s_c; static D* s_d; };
// ServiceLocator.cpp #include "ServiceLocator.h" #include "A.h" #include "B.h" #include "C.h" #include "D.h" A* ServiceLocator::s_a = nullptr; B* ServiceLocator::s_b = nullptr; C* ServiceLocator::s_c = nullptr; D* ServiceLocator::s_d = nullptr;
修改业务类(以A类为例):
// A.h #pragma once #include "ServiceLocator.h" class A { private: dataStructA data; public: void someOperation() { auto& b = ServiceLocator::getB(); // 访问b的data... auto& c = ServiceLocator::getC(); // 访问c的data... } };
在builder.cpp中初始化:
// builder.cpp #include "A.h" #include "B.h" #include "C.h" #include "D.h" #include "ServiceLocator.h" A a; B b; C c; D d; ServiceLocator::init(a, b, c, d);
2. 延迟绑定(延迟初始化引用)
给每个类添加init方法,先通过默认构造创建所有对象,再统一调用init传入所需引用,避免构造阶段的循环依赖。
示例代码(以A类为例):
// A.h #pragma once class B; class C; class A { private: dataStructA data; B* m_b = nullptr; C* m_c = nullptr; public: A() = default; void init(B& b, C& c) { m_b = &b; m_c = &c; } void someOperation() { if (m_b && m_c) { // 使用m_b、m_c访问数据... } } };
在builder.cpp中完成初始化:
// builder.cpp #include "A.h" #include "B.h" #include "C.h" #include "D.h" A a; B b; C c; D d; a.init(b, c); b.init(d); c.init(a, d);
二、允许动态内存分配时的重构思路
1. 依赖注入容器(DI Container)
实现轻量DI容器,负责创建对象实例并自动注入依赖,容器会处理对象创建顺序,解决循环依赖问题(可通过注入指针/智能指针或延迟初始化实现)。
示例简化版容器:
// DIContainer.h #pragma once #include <memory> #include <unordered_map> #include <typeindex> class DIContainer { public: template<typename T> void registerInstance(std::unique_ptr<T> instance) { m_instances[typeid(T)] = std::move(instance); } template<typename T> T& get() { return *static_cast<T*>(m_instances.at(typeid(T)).get()); } private: std::unordered_map<std::type_index, std::unique_ptr<void>> m_instances; };
使用方式:
// builder.cpp #include "DIContainer.h" #include "A.h" #include "B.h" #include "C.h" #include "D.h" DIContainer container; container.registerInstance(std::make_unique<D>()); container.registerInstance(std::make_unique<B>(container.get<D>())); container.registerInstance(std::make_unique<C>(container.get<A>(), container.get<D>())); container.registerInstance(std::make_unique<A>(container.get<B>(), container.get<C>()));
2. 接口抽象与依赖倒置
将类的对外功能抽象为纯虚接口,让类依赖抽象而非具体实现,从根本降低耦合度,同时避免编译期循环依赖。
示例:
// IDataProviderB.h #pragma once struct dataStructB; class IDataProviderB { public: virtual const dataStructB& getBData() const = 0; virtual ~IDataProviderB() = default; };
B类实现接口:
// B.h #pragma once #include "IDataProviderB.h" struct dataStructB; class B : public IDataProviderB { private: dataStructB data; public: const dataStructB& getBData() const override { return data; } };
A类依赖抽象接口:
// A.h #pragma once #include "IDataProviderB.h" #include "IDataProviderC.h" struct dataStructA; class A { private: dataStructA data; IDataProviderB& m_bProvider; IDataProviderC& m_cProvider; public: A(IDataProviderB& bProvider, IDataProviderC& cProvider) : m_bProvider(bProvider), m_cProvider(cProvider) {} void someOperation() { const auto& bData = m_bProvider.getBData(); // 操作bData... } };
3. 智能指针管理循环依赖
对于互相依赖的对象,使用std::weak_ptr配合std::shared_ptr打破循环引用,确保对象能被正确释放。例如A持有C的shared_ptr,C持有A的weak_ptr。
内容的提问来源于stack exchange,提问作者BenRa27
相关产品推荐
相关产品推荐

