假设我有这些课程:
struct Engine {
int engine_data;
};
struct Car {
shared_ptr<Engine> engine;
int car_data;
};
出于性能原因,我想把它们紧紧地包装在内存中(但我不想失去设计的灵活性)。因此,我可以创建一个“打包”结构,以及一个透明地返回新B实例的工厂:
struct PackedCarAndEngine {
Engine engine;
Car car;
};
shared_ptr<Car> new_Car() {
shared_ptr<PackedCarAndEngine> packed = make_shared<PackedCarAndEngine>();
// uses aliasing shared_ptr constructor
packed->car.engine = shared_ptr<Engine>(packed, &packed->engine);
// again
shared_ptr<Car> car = shared_ptr<Car>(packed, &packed->car);
return car;
}
问题是这个“car”实例永远不会被销毁,因为它的引用数为2。当它死亡时,它将具有永久的引用计数。你知道一个更好的方法来继续使用内部的shared_ptr(这样我可以根据需要设置一个“解压缩的”引用),并且仍然使这个打包结构?
更新
我可以使用no-op删除器,但如果我决定保留engine
而不是car
,则会非常危险:
// ...
packed->car.engine = shared_ptr<Engine>(&packed->engine, do_nothing_deleter);
// ...
shared_ptr<Car> my_car = new_Car();
shared_ptr<Engine> my_engine = my_car->engine;
my_car.reset(); // Danger: engine was destroyed here!!!
cout << my_engine->engine_data; // Crash!
答案 0 :(得分:1)
考虑在weak_ptr
内使用shared_ptr
代替struct Car
,它不会对参考计数产生影响,但可以在需要时转换为shared_ptr
。
答案 1 :(得分:0)
void nop(Engine*) { /* do nothing */ }
packed->car.engine = shared_ptr<Engine>(&packed->engine, nop);
说明:此代码创建一个shared_ptr,认为它拥有引擎,但实际上它有一个单独的引用计数器,并且在调用删除器时它什么都不做。