It is said here that it's because of exception specification. I do not understand it. Does this question have any relationship with exception specification?
After reading through the tutorial I was a little confused myself by the wording. But I believe it's as simple as this: the tutorial was explaining why the allocator's template header shows
allocator(const allocator&) throw();
and
template <class U> allocator(const allocator<U>&) throw();
even though the copy constructor is fairly useless for an allocator. And the answer was that the specification of an allocator does not allow the constructor to throw exceptions. Therefore the copy constructor public interface defines copy constructors with an exception specification of throw()
(does not throw any exceptions) to prevent someone deriving their own allocator with copy constructors which might throw an exception.
See this link for a good description of what an exception specification is if that's what was throwing you. (No pun intended. Really.)
So, they didn't mean that when creating an allocator, you have to provide a copy constructor. They just were pointing out that the specification specifically prohibits you from defining one that throws any exceptions. `
You have to explicitly write a copy constructor (rather than use the default) because the copy constructor for a C++03 allocator is required to be defined with the exception specifier throw()
. The default copy constructor does not have this specifier.
Technically, you don't have to, but if it does throw an exception... well, good luck with that.
But that's just a minor annoyance, since allocators in C++03 cannot have state. So you shouldn't be copying members around. The copy constructor can be empty.
throw()
or noexcept
). The compiler-generated copy constructor is still a copy constructor and is just fine for many allocator types. The std::allocator
template has a copy constructor explicitly specified as having a noexcept
specifier, just because it helps the compiler a little (though not much, honestly -- it's mostly historical). –
Earlearla The allocator requires a copy constructor because containers have a copy constructor and will need to copy their allocator in the process.
select_on_container_X_Y
methods. See the allocator traits reference –
Dharma It's actually pretty simple. The constructor of a container using an allocator takes the allocator and stores a copy of it. In order to do that, it needs the allocator to be CopyConstructible
. That's all. Note that an allocator type not required to CopyAssignable
unless its propagate_on_container_copy_assignment
trait is true (which is rare).
The C++11 specification also states that "No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception." The exception rules allow you to make a (stack) copy of an allocator (especially during construction or destruction) without worrying that copying the allocator will throw. Designing containers that are exception-safe in the presence of allocators that might throw on copy, move, swap, or compare is nearly impossible. In practice, an allocator cannot hold much more than a pointer to some resource, so allowing allocators to throw on copy, etc., would add a lot of pain for virtually no gain.
© 2022 - 2024 — McMap. All rights reserved.
noexcept
orthrow()
specification (though it is is a good idea to add that. The reason that allocators must be copy constructible is that the container classes store a copy of the allocator. (BTW, I wrote about 2/3 of the allocator text in the standard, starting with C++11, but allocators were required to be copy constructible from the very beginning.) – Earlearla