2

假设我有这些课程:

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;
}

问题是这个“汽车”实例永远不会被销毁,因为它的引用计数为 2。当它死亡时,它的引用计数将永远为 1。您是否知道继续使用内部 shared_ptr 的更好方法(以便我可以根据需要将“未打包”引用归因于),并且仍然制作此打包结构?

更新

我可以使用无操作删除器,但是如果我决定保留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!
4

2 回答 2

1

考虑使用weak_ptr代替shared_ptrinside struct Car,它不会增加引用计数,但可以shared_ptr在需要时转换为 a。

于 2010-12-14T12:23:53.370 回答
0
void nop(Engine*) { /* do nothing */ }

packed->car.engine = shared_ptr<Engine>(&packed->engine, nop);

说明:此代码创建了一个 shared_ptr,它认为它拥有引擎,但实际上它有一个单独的引用计数器,并且在调用删除器时它什么也不做。

于 2010-12-14T12:14:52.397 回答