You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何在部分类实例间共享单个大对象(非静态成员)?

嘿,这个需求太常见了——毕竟大型对象拷贝成本高,而且静态成员是全局共享,完全不符合你“只让部分实例共享”的要求。我给你几个实用的解决方案,都是生产环境里常用的:

方案1:使用std::shared_ptr共享对象(最推荐)

C++标准库的std::shared_ptr是专门用来处理共享所有权场景的智能指针,它会自动维护引用计数:当最后一个持有该指针的实例被销毁时,大型对象才会被自动释放。这种方式既安全又省心,完全不需要手动管理内存。

举个代码例子:

#include <memory>
#include <iostream>

// 你的大型对象类
class LargeObject {
public:
    LargeObject() { std::cout << "大型对象已创建\n"; }
    ~LargeObject() { std::cout << "大型对象已销毁\n"; }
    void performOperation() { std::cout << "正在使用大型对象执行操作\n"; }
};

// 需要共享大型对象的类
class Consumer {
private:
    std::shared_ptr<LargeObject> shared_obj;
public:
    // 构造时传入共享指针,明确指定要共享的对象
    Consumer(std::shared_ptr<LargeObject> obj) : shared_obj(std::move(obj)) {}
    
    void useLargeObject() {
        shared_obj->performOperation();
    }
};

int main() {
    // 创建一个大型对象,用shared_ptr管理
    auto shared_large_obj = std::make_shared<LargeObject>();

    // 这两个Consumer实例共享同一个大型对象
    Consumer c1(shared_large_obj);
    Consumer c2(shared_large_obj);
    c1.useLargeObject();
    c2.useLargeObject();

    // 这个Consumer实例使用独立的大型对象
    Consumer c3(std::make_shared<LargeObject>());
    c3.useLargeObject();

    return 0;
}

运行这段代码你会看到:第一个大型对象会在c1、c2都销毁后才被释放,而第三个大型对象会在c3销毁时就释放,完美实现了“部分实例共享”的需求。

方案2:手动传递裸指针(需谨慎使用)

如果你不想用智能指针,也可以直接传递裸指针,但必须严格控制大型对象的生命周期——确保大型对象的存活时间比所有共享它的Consumer实例更长,否则会出现悬空指针的问题。

示例代码:

#include <iostream>

class LargeObject {
public:
    LargeObject() { std::cout << "大型对象已创建\n"; }
    ~LargeObject() { std::cout << "大型对象已销毁\n"; }
    void performOperation() { std::cout << "正在使用大型对象执行操作\n"; }
};

class Consumer {
private:
    LargeObject* obj_ptr;
public:
    Consumer(LargeObject* ptr) : obj_ptr(ptr) {}
    
    void useLargeObject() {
        obj_ptr->performOperation();
    }
};

int main() {
    // 手动创建大型对象,必须保证它比所有Consumer先创建、后销毁
    LargeObject* shared_obj = new LargeObject();

    Consumer c1(shared_obj);
    Consumer c2(shared_obj);
    c1.useLargeObject();
    c2.useLargeObject();

    // 另一个独立的大型对象
    LargeObject* independent_obj = new LargeObject();
    Consumer c3(independent_obj);
    c3.useLargeObject();

    // 手动释放内存,注意顺序:先销毁所有Consumer,再释放大型对象
    delete independent_obj;
    delete shared_obj;

    return 0;
}

⚠️ 注意:这个方案容易出错,比如不小心提前释放了大型对象,或者Consumer实例存活时间超过了大型对象,都会导致程序崩溃,所以除非有特殊原因,否则优先用智能指针。

方案3:依赖注入+工厂模式(更易维护)

如果你的项目比较复杂,想把共享逻辑集中管理,可以用依赖注入结合工厂模式:通过工厂类来决定哪些Consumer实例共享同一个大型对象,哪些使用独立对象,这样后续修改共享规则会非常方便。

示例代码:

#include <memory>
#include <iostream>

class LargeObject {
public:
    LargeObject() { std::cout << "大型对象已创建\n"; }
    ~LargeObject() { std::cout << "大型对象已销毁\n"; }
    void performOperation() { std::cout << "正在使用大型对象执行操作\n"; }
};

class Consumer {
private:
    std::shared_ptr<LargeObject> shared_obj;
public:
    Consumer(std::shared_ptr<LargeObject> obj) : shared_obj(std::move(obj)) {}
    
    void useLargeObject() {
        shared_obj->performOperation();
    }
};

// 工厂类,负责创建Consumer并控制共享逻辑
class ConsumerFactory {
private:
    std::shared_ptr<LargeObject> shared_large_obj;
public:
    ConsumerFactory() {
        // 预先创建一个共享的大型对象
        shared_large_obj = std::make_shared<LargeObject>();
    }

    // 创建共享大型对象的Consumer
    std::unique_ptr<Consumer> createSharedConsumer() {
        return std::make_unique<Consumer>(shared_large_obj);
    }

    // 创建使用独立大型对象的Consumer
    std::unique_ptr<Consumer> createIndependentConsumer() {
        return std::make_unique<Consumer>(std::make_shared<LargeObject>());
    }
};

int main() {
    ConsumerFactory factory;

    // 这两个实例共享同一个大型对象
    auto c1 = factory.createSharedConsumer();
    auto c2 = factory.createSharedConsumer();
    c1->useLargeObject();
    c2->useLargeObject();

    // 这个实例用独立对象
    auto c3 = factory.createIndependentConsumer();
    c3->useLargeObject();

    return 0;
}

这种方式的好处是,所有共享逻辑都封装在工厂里,如果你之后想调整哪些实例需要共享,只需要修改工厂的方法即可,不需要改动Consumer类的代码,符合开闭原则。


内容的提问来源于stack exchange,提问作者P.N.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:22:05