Supposons que j'ai ces classes:Comment gérer shared_ptr qui pointe vers les données internes d'un objet déjà référencé?
struct Engine {
int engine_data;
};
struct Car {
shared_ptr<Engine> engine;
int car_data;
};
Pour des raisons de performance, je veux les rendre bien emballés dans la mémoire (mais je ne veux pas perdre la flexibilité de la conception). Donc, je peux créer une structure « tassée », et une usine qui sera de retour en toute transparence une nouvelle instance 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;
}
Le problème est que cette instance « voiture » ne sera jamais détruit, parce qu'il a un compte de référence de deux. Quand il meurt, il aura un compte de référence d'un, pour toujours. Savez-vous un meilleur moyen de continuer à utiliser le shared_ptr interne (de sorte que je peux attribuer une référence "déballé" si je veux), et encore faire cette structure emballée?
MISE À JOUR
je pouvais utiliser un no-op Deleter, mais il serait très dangereux si je décide de garder le engine
mais pas le 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!
Pourquoi ne faites-vous pas d'un moteur un membre droit de Car? Si vous créez toujours une voiture et un moteur dans le même objet, cela signifie qu'ils ont la même durée de vie. La voiture connaît le moteur mais pas l'inverse. Sauf si vous envisagez de partager la même instance de moteur entre différentes instances de Car ne serait pas 'struct Car {engine Engine; int car_data; }; 'être un design plus simple? –
@Charles J'ai réfléchi à cela ... au cas où je ne pourrais pas résoudre le problème facilement avec 'shared_ptr', je reviendrai sur cette solution. Dans cet exemple, j'ai donné, je n'ai qu'une seule composition, mais dans mon vrai design, j'ai beaucoup de classes composées de cette façon, en plusieurs couches, et je veux avoir la flexibilité d'assigner différents moteurs provenant d'autres endroits . –