In this context T
is a certain type and allocator
is an allocator object for that type. By default it is std::allocator<T>
but this is not necessarily true.
I have a chunk of memory acquired by allocator.allocate(n)
. I also have a container con
of T
objects (say, a std::vector<T>
). I want to initialize that chunk of memory with the T
object(s).
The location of the chunk of memory is stored in T* data
.
Are these two code examples always identical?
#include <memory>
/开发者_StackOverflow/ example 1
std::uninitialized_copy(con.begin(), con.end(), data)
// example 2
std::vector<T>::const_iterator in = con.begin();
for (T* out = data; in != con.end(); ++out, ++in) {
allocator.construct(out, *in);
}
And for these two?
#include <memory>
T val = T(); // could be any T value
// example 3
std::uninitialized_fill(data, data + n, val)
// example 4
for (T* out = data; out != (data + n); ++out) {
allocator.construct(out, val);
}
According to this explanations They should do the same, as allocator::construct
is said to construct the object and std::uninitialized...
also constructs the objects. But I do not know, what exactly the standard says and what freedom you have, when implementing your own allocator::construct
.
EDIT: Ok, the C++03 standard states in section 20.1.5 §2 table 32, that construct(p,t)
should have the same effect as new ((void*)p) T(t)
(for any standard compliant allocator, not only std::allocator
). And in 20.4.4.1 §1, that uninitialized_copy
should have the same effect as
for (; first != last; ++result, ++first)
new (static_cast<void*>(&*result))
typename iterator_traits<ForwardIterator>::value_type(*first);
and in 20.4.4.2 §1, that uninitialized_fill
has an effect of
for (; first != last; ++first)
new (static_cast<void*>(&*first))
typename iterator_traits<ForwardIterator>::value_type(x);
So I think that doesn't leave any room for them to behave differently. So to answer your question: yes, it does.
C++ Primer 5th §13.6.2:
.....
uninitialized_copy
callsconstruct
on each element in the input sequence to “copy” that element into the destination. That algorithm uses the iterator dereference operator to fetch elements from the input sequence. Because we passed move iterators, the dereference operator yields an rvalue reference, which meansconstruct
will use the move constructor to construct the elements.
.....
精彩评论