Утилизировать старую переменную, используемую для построения полезного значения

Предположим следующие два класса:

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 ++ для решения этого типа проблем?

0

Решение

Вы можете назначить объект по умолчанию для 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 экземпляр лежал вокруг.

1

Другие решения

Во многом это зависит от классов, которые вы создали в своей программе. И то и другое A а также B должен иметь общий протокол (или суб-протокол для другого класса) и общее хранилище, подразумевающее этот протокол (например, vector какой-то обычай struct). Если это так, класс, несущий ответственность, может иметь функцию для ресурсы делегация (лайк set_owner), который может использовать другой класс. Шаблон в значительной степени (или полностью) зависит от имеющихся у вас классов / ресурсов / шаблонов.

Если существует некоторый общий протокол, один или оба (или несколько) классов могут быть изменены соответствующим образом.

Если классы схожи (например, с наследованием или вложенными классами), то возвращаемое значение-оптимизация, Name-RVO или move конструкции могут быть использованы.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector