Какие обьекты удалять в деструкторе?
После того, как отработает тело деструктора, для всех полей объекта автоматически вызываются деструкторы, в обратном порядке.
У int и double деструкторы нулевые — но другие-то и не нужны.
В каких случаях надо писать деструктор самим…
1. Мы владеем каким-то ресурсом, но штатный деструктор его не уничтожает.
• Простой (не умный) указатель и выделенная память — это хорошо описал sitev_ru .
• Объект-блокировщик, например, мьютекса (мьютекс — примитив межпоточной синхронизации, не дающий зайти в определённые участки кода одновременно двум потокам).class Mutex {
public:
  void enter();
  void leave();
}

class Lock {
public:
  Lock(Mutex& aMutex) : mutex(aMutex) { mutex.enter(); }
  ~Lock() { mutex.leave(); }
private:
  Mutex& mutex;
}

…
Mutex mutex;
{ Lock lock(mutex);
  // всё, что здесь, выполняется внутри мьютекса.
  // Даже если выпадет авария, из мьютекса корректно выйдем.
}
2. Сложный порядок уничтожения. Односвязный список из std::unique_ptr будет работать и так, со штатным деструктором, но это чревато переполнением стека.
3. Сложная структура владения, и при уничтожении надо автоматически отобрать объект у владельцев. По-чёрному используется в оконных фреймворках на манер VCL и Qt. Удаляем компонент — он автоматически отбирается у владельца.
По опыту: если структуры данных выносить в отдельный объект (ну и использовать STL, где можно), 80% объектов Си++ будут с автоматическим деструктором.
ЗЫ. По результатам прикидочных подсчётов в живом проекте, ≈150 файлов (реально файлов 219, но не все наши собственные; библиотечные деструкторы не учитывал).
• Классов с настоящим деструктором — около 30. Большей частью системные (W32Cs — быстрый мьютекс Win32) или структуры памяти (Array1d, например). Из них в собственно проекте (не в личной библиотеке программиста) — три (!): один связан с автовладением чужой библиотекой XLSX, два — с фоновыми потоками.
• Интерфейсов с пустым виртуальным деструктором — порядка 40.
• И ещё деструкторы, автоматически добавленные Qt — по числу форм, ровно 20.
• И единицы пустых деструкторов, добавленных по желанию левой пятки линкера.
class B {...};
class A {
	A() {
		b = new B();
	}
	~A() {
		delete b;
	}
};
В деструкторе удаляем объекты, созданные в динамической памяти.