Another thing to consider is exception safety: what happens if memory is allocated or an object is copied? In this case, you should try to make your class as efficient as possible. Consider the following warranties:
- No guarantee: if something goes wrong, the object may be in an invalid state
- Weak guarantee: if something goes wrong, the object is in undefined, but valid, state
- Strong guarantee: if something goes wrong, the object has not changed
- No-throw guarantee: nothing can go wrong.
You cannot achieve the latter here, since you do not have control over the memory allocator or objects that need to be copied. Nevertheless, a “strong” guarantee is possible using a two-stage approach: do work that may not work “sideways”, so that it does not affect the visible state; as soon as this works, update the persistent state using operations that cannot fail (for example, updating pointers and deleting old memory - if deleting gives a "no-throw" guarantee, which usually should).
Thus, a safer version with exceptions might look something like this:
if (new_size > capacity) { allocate new storage, controlled by a local smart pointer copy old values copy new values update state, releasing the smart pointer delete old storage } else { copy new values }
The "else" case here offers only a "weak" guarantee: if any object cannot copy, then some, but not all, of the new data can be copied. Improving this will cost either in terms of complexity (providing a way to “soak” the changes upon failure) and speed and memory (using the redistributable version, is there enough memory or not).
Mike seymour
source share