Предположим следующие два класса:
struct A {
A() {}
};
struct B {
B(const A& a) {}
};
Несколько раз мне приходилось сталкиваться с ситуацией, когда мне приходилось создавать временный экземпляр класса, чтобы создать экземпляр того, что мне нужно использовать. Что-то вроде:
A a;
// Do very complex computations using a;
B b(a);
// use b, a is not needed anymore.
return make_result(b);
Моя проблема в том, что иногда ресурсы a
после того, как мои вычисления могут быть значительными, и после того, как я создаю b
Я хотел бы выпустить их. В то же время весь процесс a -> b -> result
логически очень компактная вещь, и я хотел бы избежать разбиения ее на функции, так как в таком случае будет почти нечего.
Какие существуют решения в C ++ для решения этого типа проблем?
Вы можете назначить объект по умолчанию для A
, при условии, что A
Оператор присваивания должным образом освобождает «ресурсы»:
A a;
// Do very complex computations using a;
B b(a);
a = {};
// use b, a is not needed anymore.
return make_result(b);
Вы могли бы изменить B
принять A
по значению и переместить построенный A
экземпляр в B
:
struct A {
A() {}
};
struct B {
B(A a) {}
};
// ...
A a;
// Do very complex computations using a;
B b(std::move(a));
// use b, a is not needed anymore.
return make_result(b);
который имеет хорошее преимущество в том, что B
конструктор может «украсть» ресурсы из A
объект.
Вы можете использовать лямбду для построения A
и передать его B
:
B b([&]{
A a;
// Do very complex computations using a;
return a;
}());
// use b, a is not needed anymore.
return make_result(b);
Вы могли бы оба построить A
с лямбдой а также иметь B
возьмите это по значению:
struct A {
A() {}
};
struct B {
B(A a) {}
};
// ...
B b([&]{
A a;
// Do very complex computations using a;
return a;
}());
// use b, a is not needed anymore.
return make_result(b);
который позволяет B
украсть вещи из A
но не оставляет зомби A
экземпляр лежал вокруг.
Во многом это зависит от классов, которые вы создали в своей программе. И то и другое A
а также B
должен иметь общий протокол (или суб-протокол для другого класса) и общее хранилище, подразумевающее этот протокол (например, vector
какой-то обычай struct
). Если это так, класс, несущий ответственность, может иметь функцию для ресурсы делегация (лайк set_owner
), который может использовать другой класс. Шаблон в значительной степени (или полностью) зависит от имеющихся у вас классов / ресурсов / шаблонов.
Если существует некоторый общий протокол, один или оба (или несколько) классов могут быть изменены соответствующим образом.
Если классы схожи (например, с наследованием или вложенными классами), то возвращаемое значение-оптимизация, Name-RVO или move
конструкции могут быть использованы.