Шаблоны для сброса объектов в исходное состояние

Предположим, у меня есть объект с элементом, который дорого построить, и потребность в reset() функция, которая сбрасывает его в исходное состояние:

struct Example
{
// option 1: efficient, but need to duplicate initialization logic of reset()
Example(int param) : expensive_member_(param), param_(param)
{
}
/* option 2: less code, but initializes expensive_member_ twice
Example(int param) : param_(param)
{
reset();
}*/

void reset()
{
expensive_member_ = ClassWithExpensiveConstructor(param_);
}

ClassWithExpensiveConstructor expensive_member_;
int param_;
}

Есть ли лучший способ / шаблон для эффективного сброса объекта в исходное состояние без дублирования логики инициализации в списке инициализатора и reset функционировать?

редактировать: Если нет общего способа достичь того, чего я хочу, это также является приемлемым результатом этого вопроса!

3

Решение

Вы можете сделать свой ExpensiveMember указатель, в таком случае ваш вариант 2 не будет вызывать ExpensiveMember конструктор в Example конструктор, если вы явно не вызываете его:

struct Example
{
Example(int param) : expensive_member_(), param_(param)
{
reset();
}

~Example() {
delete expensive_member_;   // better use unique_ptr etc
}

// Also a copy constructor and assignment operator
// are needed to avoid memory problems such as double-delete.
// Also, better use unique_ptr etc.
// This answer does not use unique_ptr just to make the main idea more clear.

void reset()
{
delete expensive_member_;   // better use unique_ptr etc
expensive_member_ = new ClassWithExpensiveConstructor(param_);
}

ClassWithExpensiveConstructor* expensive_member_;  // better use unique_ptr etc
int param_;
}
1

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

Если ClassWithExpensiveConstructor это тот класс, чья конструкция / сброс дорогая, именно она должна оптимизировать работу.

Другим вариантом будет сохранить копию начального значения в const член, предполагая, что копирование конструкции / назначения не дорого. Это будет использовать больше памяти, но улучшить производительность, если вы звоните Example::reset() много.

struct Example
{
Example(int param)
: expensive_member_backup_(param)
, expensive_member_(expensive_mamber_backup)
, param_(param)
{
}

void reset()
{
expensive_member_ = expensive_member_backup_;
}

const ClassWithExpensiveConstructor expensive_member_backup_;
ClassWithExpensiveConstructor expensive_member_;
int param_;
}
1

Простым решением было бы использование (интеллектуального или обычного) указателя, так что стоимость инициализации элемента (то есть указателя) становится меньше, а фактический объект инициализируется только при вызове reset():

 struct Example
{
Example(int param) : param_(param)
{
reset();
}

void reset()
{
p.reset(new ClassWithExpensiveConstructor(param_));
}

unique_ptr<ClassWithExpensiveConstructor> p;
int param_;
}
1
По вопросам рекламы [email protected]