Avoid overallocation in PODArray assignment

Part of #12438
This commit is contained in:
Alexander Kuzmenkov 2020-08-07 18:18:32 +03:00
parent 5d60ab33a5
commit c06210a89a

View File

@ -220,6 +220,13 @@ public:
realloc(roundUpToPowerOfTwoOrZero(minimum_memory_for_elements(n)), std::forward<TAllocatorParams>(allocator_params)...);
}
template <typename ... TAllocatorParams>
void reserve_exact(size_t n, TAllocatorParams &&... allocator_params)
{
if (n > capacity())
realloc(minimum_memory_for_elements(n), std::forward<TAllocatorParams>(allocator_params)...);
}
template <typename ... TAllocatorParams>
void resize(size_t n, TAllocatorParams &&... allocator_params)
{
@ -227,6 +234,13 @@ public:
resize_assume_reserved(n);
}
template <typename ... TAllocatorParams>
void resize_exact(size_t n, TAllocatorParams &&... allocator_params)
{
reserve_exact(n, std::forward<TAllocatorParams>(allocator_params)...);
resize_assume_reserved(n);
}
void resize_assume_reserved(const size_t n)
{
c_end = c_start + byte_size(n);
@ -601,7 +615,7 @@ public:
template <typename... TAllocatorParams>
void assign(size_t n, const T & x, TAllocatorParams &&... allocator_params)
{
this->resize(n, std::forward<TAllocatorParams>(allocator_params)...);
this->resize_exact(n, std::forward<TAllocatorParams>(allocator_params)...);
std::fill(begin(), end(), x);
}
@ -612,7 +626,7 @@ public:
size_t required_capacity = from_end - from_begin;
if (required_capacity > this->capacity())
this->reserve(roundUpToPowerOfTwoOrZero(required_capacity), std::forward<TAllocatorParams>(allocator_params)...);
this->reserve_exact(required_capacity, std::forward<TAllocatorParams>(allocator_params)...);
size_t bytes_to_copy = this->byte_size(required_capacity);
memcpy(this->c_start, reinterpret_cast<const void *>(&*from_begin), bytes_to_copy);