Самый короткий и лучший способ "повторно инициализировать" /очистить экземпляр класса

Я буду держать его коротким и просто покажу вам пример кода:

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

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

Хорошо. Если у меня есть экземпляр myClass и установите некоторый случайный мусор для a, b и c.

  • Каков наилучший способ для reset их всех в состояние после вызова конструктора класса, поэтому: 0, 0 и 0?

Я подошел так:

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

или..

myUsedInstance.a = 0; myUsedInstance.c = 0; myUsedInstance.c = 0; 
  • Я думаю, вы знаете, чего я хочу, есть ли лучший способ достичь этого?

Ответ 1

myUsedInstance = myClass();

С++ 11 очень эффективен, если вы используете эту форму; оператор назначения перемещения позаботится о том, чтобы вручную очистить каждый элемент.

Ответ 2

Вы можете реализовать clear в качестве общей функции для любого типа swappable. (Тип, подлежащий замене, является общим и выполняется неявно в С++ 0x с конструктором перемещения. Если у вас есть конструктор копирования и оператор присваивания, которые ведут себя надлежащим образом, тогда ваш тип автоматически заменяется в текущем С++. Вы можете также легко настраивать подкачку для ваших типов.)

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

Для этого требуется наименьшая работа от вас, хотя она может показаться несколько более сложной, потому что она должна выполняться только один раз, а затем работает практически везде. Он использует идиому с пустой заменой для учета классов (например, std::vector), которые не очищают все при назначении.


Если вы видели, что swap является узким местом производительности (что было бы редко), специализируйтесь на нем (не изменяя использование clear !) в заголовке myClass:

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

Если myClass является шаблоном, вы не можете частично специализировать clear, но вы можете перегрузить его (снова в заголовке класса):

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

Поводом для определения такой специализации или перегрузки в заголовке myClass является упрощение того, чтобы не нарушать ODR, предоставляя их в одном месте, а не в другом. (I.e. они всегда доступны, если myClass доступен.)

Ответ 3

Просто назначьте класс, построенный по умолчанию, как и у вас. Просто используйте временную, хотя:

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

Ответ 4

Возможно, вы захотите рассмотреть возможность использования нового места размещения. Это позволит вам использовать одну и ту же память, но снова вызовет конструктор.

Однако не забудьте вызвать деструктор, прежде чем использовать новое место размещения.