Too often we hear "I do not want to use exceptions because they are inefficient."
Unless you are referring to an “embedded” environment in which you want to disable all information about runtime type, you should not worry too much about the inefficiencies of exceptions if they are thrown appropriately. Running from memory is one of the following methods.
Part of the vector contract is that it will throw if it cannot highlight. If you write a custom allocator that returns NULL instead, this will be worse, as this will lead to undefined behavior.
If you need to use a dispenser that first tries to make a callback with failures, if one is available, and only if you still cannot allocate a throw, but still you should get an exception.
Can I give you a hint: if you really allocate such large amounts of data, then the vector is probably the wrong class, and you should use std :: deque instead. What for? Since deque does not require a continuous block of memory, but still a constant time search. And the benefits are doubled:
- Allocations will occur less frequently. Because you do not need a continuous block, so you can have available memory, although not in one block.
- Redistribution does not exist, but more so. Redistribution is expensive because it requires the movement of all objects. When you are in high volume mode, which can be very timely.
When I worked on such a system in the past, we found that we could store 4 times as much data using deque, as we could use the vector because of reason 1 above, and it was faster because of reason 2.
Something else we did was allocate a 2 MB backup buffer, and when we caught bad_alloc, we freed the buffer, and then still show that we reached capacity. But with the spare 2 MB, we at least knew that we had the memory to perform small operations to move data from memory to temporary disk storage.
Thus, we could sometimes catch bad_alloc and take the appropriate action, maintaining a consistent state, which is the purpose of exceptions, and not assume that running out of memory is always fatal and should never do anything but terminate the program (or even worse, cause undefined behavior) .