如何消除std::unique_ptr冗余解引用导致的效率低下问题?
解决方案
针对你遇到的std::unique_ptr成员导致两次解引用的性能问题,以下是几种更简洁高效的替代方案:
方案一:缓存原始指针到类成员
在类中新增一个原始指针成员,初始化时绑定到unique_ptr指向的地址,后续只要unique_ptr不被重置,该指针就始终有效。这样在虚函数中直接使用缓存的原始指针,就能将两次解引用减少为一次。
class SomeObject { std::unique_ptr<int> someUnique; int* someRaw; // 缓存原始指针 public: // 构造时同步绑定指针 SomeObject() : someUnique(std::make_unique<int>(42)), someRaw(someUnique.get()) {} // 若需要重置unique_ptr,同步更新缓存指针 void reset(std::unique_ptr<int> newPtr) { someUnique = std::move(newPtr); someRaw = someUnique.get(); } // 虚函数直接使用缓存指针,仅一次解引用 virtual void operate() { *someRaw += 1; } };
注意:单线程场景下该方案零额外开销;若存在多线程修改unique_ptr的场景,需同步更新缓存指针,避免出现悬空指针。
方案二:分离所有权与业务对象,复用通用工厂函数
你之前的Unit方案核心思路可行,但可以通过通用模板工厂函数避免每个类都编写Make()方法,减少代码膨胀:
// 业务类仅持有原始指针,不管理所有权 class SomeObject { int* data; public: explicit SomeObject(int* ptr) : data(ptr) {} virtual void doWork() { *data *= 2; // 一次解引用 } }; // 通用工厂函数,自动创建资源并绑定业务对象 template<typename BusinessObj, typename Resource, typename... Args> auto create_bound_object(Args&&... args) { auto resource = std::make_unique<Resource>(std::forward<Args>(args)...); return std::pair<std::unique_ptr<Resource>, BusinessObj>( std::move(resource), BusinessObj(resource.get()) ); } // 使用方式 auto [resourceHolder, obj] = create_bound_object<SomeObject, int>(10); obj.doWork();
这个方案将所有权统一交给外部的unique_ptr管理,业务类仅持有无所有权的原始指针,同时通用工厂函数可复用在所有需要绑定资源的类上,无需重复编写创建逻辑。
方案三:使用std::reference_wrapper(针对特定场景)
如果unique_ptr指向的对象生命周期完全由外部控制,且不会在业务对象使用期间被销毁,可以将业务类改为持有std::reference_wrapper而非指针:
class SomeObject { std::reference_wrapper<int> dataRef; public: explicit SomeObject(int& ref) : dataRef(ref) {} virtual void modify() { dataRef.get() += 5; // 直接访问引用,无额外解引用 } }; // 使用方式 auto data = std::make_unique<int>(20); SomeObject obj(*data); obj.modify();
该方案完全避免了指针解引用,但要求引用的对象在业务对象生命周期内必须始终有效,适合生命周期明确绑定的场景。
内容的提问来源于stack exchange,提问作者Bipolo
相关产品推荐
相关产品推荐

