One nifty trick to avoid writing new or delete even when you need manual heap allocation is to always use std::make_unique (or std::make_shared, as needed) instead. That way you're forced to spell out any transfer of ownership as it is happening, and so someone's always be sure to delete the object. You also dodge the bullet with indeterminate ordering of new's and constructors, that might result in memory leaks if one of the constructors throws.
An important extension to this trick is that unique_ptr and shared_ptr are specialized for arrays. So e.g. to allocate a dynamic array of size n, you can do:
auto a = std::make_unique<char[]>(100);
or auto a = std::make_unique<int[3]>(1, 2, 3);
and then use it mostly like an array - a[i] is overloaded and work as expected, for example.The reason why you'd want to do this rather than using std::vector is because you don't get the overhead of overallocation (since vectors distinct capacity and size) and default-initialization of the elements.
With these, it's quite possible to write >100 kLoC of C++ without a single new or delete in sight.