开发者

How to manage shared_ptr that points to internal data of already referenced object?

开发者 https://www.devze.com 2023-01-30 06:23 出处:网络
Suppose I have these classes: struct Engine { int engine_data; }; struct Car { shared_ptr<Engine> engine;

Suppose I have these classes:

struct Engine {
  int engine_data;
};

struct Car {
  shared_ptr<Engine> engine;
  int car_data;
};

For performance reasons, I want to make them tightly packed in memory (but I don't want to lose the flexibility of the design). So, I can create a "packed" structure, and a factory that will transparently return a new B instance:

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

The problem is that this "car" instance will never be destroyed, because it have a reference count of two. When it dies, it will have a reference count of one, forever. Do you know a better way to keep using the internal shared_ptr's (so that I can attribute an "unpacked" reference if I want), and still make this packed structure?

UPDATE

I could use a no-op deleter, but then it would be very dangerous if I decide to keep the engine but not the 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!!!开发者_Go百科
cout << my_engine->engine_data; // Crash!


Consider using weak_ptr instead of shared_ptr inside struct Car, it does not contribute to reference count, but can be converted to a shared_ptr when needed.


void nop(Engine*) { /* do nothing */ }

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

Explanation: This code creates a shared_ptr that thinks that it owns the engine but in fact it has a separate reference counter AND it does nothing when the deleter is called.

0

精彩评论

暂无评论...
验证码 换一张
取 消