tags:

views:

175

answers:

4

I will keep it short and just show you a code example:

class myClass
{
public:
  myClass();
  int a;
  int b;
  int c;
}

// In the myClass.cpp or whatever
myClass::myClass( )
{
 a = 0;
 b = 0;
 c = 0;
}

Okay. If I know have an instance of myClass and set some random garbage to a, b and c.

  • What is the best way to reset them all to the state after the class constructor was called, so: 0, 0 and 0?

I came up with this way:

myClass emptyInstance;
myUsedInstance = emptyInstance; // Ewww.. code smell?

Or..

myUsedInstance.a = 0; myUsedInstance.c = 0; myUsedInstance.c = 0; 
  • I think you know what I want, is there any better way to achieve this?
+5  A: 
myUsedInstance = myClass();
Goz
A: 

Just assign to a default-constructed class, like you have. Just use a temporary, though:

struct foo
{
    int a, b, c;

    foo() :
    a(), b(), c()
    {} // use initializer lists
};

foo f;
f.a = f.b =f.c = 1;

f = foo(); // reset
GMan
Probably a good way but confuses the hell out of me atm.
Oper
@Oper It's the standard C++ way of doing what you asked - any reasonably experienced C++ programmer will recognise the meme.
anon
A: 

You may want to consider using placement new. This will allow you to use the same memory but call the constructor again.

Don't forget to call the destructor before using placement new, however.

taspeotis
In other words, you may not want to consider this. I would only do this under very exceptional circumstances, and even then think twice - a = A() is almost always the best bet.
anon
+4  A: 

You can implement clear as a generic function for any swappable type. (A type being swappable is common and done implicitly in C++0x with a move constructor. If you have a copy constructor and assignment operator that behave appropriately, then your type is automatically swappable in current C++. You can customize swapping for your types easily, too.)

template<class C>
C& clear(C& container) {
  C empty;
  using std::swap;
  swap(empty, container);
  return container;
}

This requires the least work from you, even though it may appear slightly more complicated, because it only has to be done once and then works just about everywhere. It uses the empty-swap idiom to account for classes (such as std::vector) which don't clear everything on assignment.


If you have seen that the swap is a performance bottleneck (which would be rare), specialize it (without having to change any use of clear!) in myClass's header:

template<>
myClass& clear<myClass>(myClass& container) {
  container = myClass();
  return container;
}

If myClass is a template, you cannot partially specialize clear, but you can overload it (again in the class header):

template<class T>
myClass<T>& clear(myClass<T>& container) {
  container = myClass<T>();
  return container;
}

The reason to define such specialization or overload in myClass's header is to make it easy to avoid violating the ODR by having them available in one place and not in another. (I.e. they are always available if myClass is available.)

Roger Pate
Great answer. :)
GMan
You might want to emphasize why you suggest this, rather than just relying on the default constructor like others suggested.
Dennis Zickefoose
@Dennis: How's this version?
Roger Pate
Its quite good as written. I mostly meant this line: "It uses the empty-swap idiom to account for classes (such as std::vector) which don't clear everything on assignment." Without those special cases, there's not much benefit to the whole setup.
Dennis Zickefoose