Reputation: 5854
Suppose I have an object with a member that is expensive to construct, and the need for a reset()
function that resets it to its initial state:
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_;
}
Is there a better way of/pattern for efficiently resetting the object to its initial state without duplicating the initialization logic in the initializer list and the reset
function?
edit: If there is no generic way of achieving what I want, that is also an acceptable outcome of this question!
Upvotes: 3
Views: 1384
Reputation: 10007
You can make your ExpensiveMember
a pointer, in such case your option 2 will not call ExpensiveMember
constructor in Example
constructor unless you explicitly call it:
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_;
}
Upvotes: 1
Reputation: 1103
A simple solution would be to use a (smart or regular) pointer, so that the cost of initializing the member (i.e. the pointer) becomes smaller, and the actual object is only initialized in the call to reset()
:
struct Example
{
Example(int param) : param_(param)
{
reset();
}
void reset()
{
p.reset(new ClassWithExpensiveConstructor(param_));
}
unique_ptr<ClassWithExpensiveConstructor> p;
int param_;
}
Upvotes: 1
Reputation: 7002
If ClassWithExpensiveConstructor
is the one class whose construction/reset is expensive, it should be it which optimizes the operation.
Another option would be to keep a copy of the initial value in a const
member, assuming that copy construction/assignment is not expensive. That would use more memory, but improve performance if you happen to call Example::reset()
a lot.
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_;
}
Upvotes: 1