Skip to content

Commit

Permalink
🔨 Fix shrink_to_fit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alinshans committed Aug 18, 2017
1 parent c702210 commit 791617c
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 24 deletions.
29 changes: 25 additions & 4 deletions MyTinySTL/basic_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ class basic_string
{ return static_cast<size_type>(-1); }

void reserve(size_type n);
void shrink_to_fit() noexcept;
void shrink_to_fit();

// 访问元素相关操作
reference operator[](size_type n)
Expand Down Expand Up @@ -698,6 +698,9 @@ class basic_string
// get raw pointer
const_pointer to_raw_pointer() const;

// shrink_to_fit
void reinsert(size_type size);

// append
template <class Iter>
basic_string& append_range(Iter first, Iter last);
Expand Down Expand Up @@ -769,12 +772,11 @@ reserve(size_type n)
// 减少不用的空间
template <class CharType, class CharTraits>
void basic_string<CharType, CharTraits>::
shrink_to_fit() noexcept
shrink_to_fit()
{
if (size_ != cap_)
{
data_allocator::deallocate(buffer_ + size_, cap_ - size_);
cap_ = size_;
reinsert(size_);
}
}

Expand Down Expand Up @@ -1678,6 +1680,25 @@ to_raw_pointer() const
return buffer_;
}

// reinsert 函数
template <class CharType, class CharTraits>
void basic_string<CharType, CharTraits>::
reinsert(size_type size)
{
auto new_buffer = data_allocator::allocate(size);
try
{
char_traits::move(new_buffer, buffer_, size);
}
catch (...)
{
data_allocator::deallocate(new_buffer);
}
buffer_ = new_buffer;
size_ = size;
cap_ = size;
}

// append_range,末尾追加一段 [first, last) 内的字符
template <class CharType, class CharTraits>
template <class Iter>
Expand Down
75 changes: 55 additions & 20 deletions MyTinySTL/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@ class vector

public:
// 构造、复制、移动、析构函数
vector()
{
init_space(0, 16);
}
vector() noexcept
{ try_init(); }

explicit vector(size_type n)
{ fill_init(n, value_type()); }
Expand Down Expand Up @@ -164,7 +162,7 @@ class vector
size_type capacity() const noexcept
{ return static_cast<size_type>(cap_ - begin_); }
void reserve(size_type n);
void shrink_to_fit() noexcept;
void shrink_to_fit();

// 访问元素相关操作
reference operator[](size_type n)
Expand Down Expand Up @@ -284,6 +282,7 @@ class vector
// helper functions

// initialize / destroy
void try_init() noexcept;

void init_space(size_type size, size_type cap);

Expand Down Expand Up @@ -318,6 +317,9 @@ class vector
template <class IIter>
void copy_insert(iterator pos, IIter first, IIter last);

// shrink_to_fit

void reinsert(size_type size);
};

/*****************************************************************************************/
Expand Down Expand Up @@ -367,21 +369,6 @@ vector<T>& vector<T>::operator=(vector&& rhs) noexcept
return *this;
}

// 放弃多余的容量
template <class T>
void vector<T>::shrink_to_fit() noexcept
{
if (end_ < cap_)
{
try
{
data_allocator::deallocate(end_ + 1, cap_ - end_);
cap_ = end_;
}
catch (...) {}
}
}

// 预留空间大小,当原容量小于要求大小时,才会重新分配
template <class T>
void vector<T>::reserve(size_type n)
Expand All @@ -400,6 +387,16 @@ void vector<T>::reserve(size_type n)
}
}

// 放弃多余的容量
template <class T>
void vector<T>::shrink_to_fit()
{
if (end_ < cap_)
{
reinsert(size());
}
}

// 在 pos 位置就地构造元素,避免额外的复制或移动开销
template <class T>
template <class ...Args>
Expand Down Expand Up @@ -553,6 +550,25 @@ void vector<T>::swap(vector<T>& rhs) noexcept
/*****************************************************************************************/
// helper function

// try_init 函数,若分配失败则忽略,不抛出异常
template <class T>
void vector<T>::try_init() noexcept
{
try
{
begin_ = data_allocator::allocate(16);
end_ = begin_;
cap_ = begin_ + 16;
}
catch (...)
{
begin_ = nullptr;
end_ = nullptr;
cap_ = nullptr;
}
}

// init_space 函数
template <class T>
void vector<T>::init_space(size_type size, size_type cap)
{
Expand Down Expand Up @@ -848,6 +864,25 @@ copy_insert(iterator pos, IIter first, IIter last)
}
}

// reinsert 函数
template <class T>
void vector<T>::reinsert(size_type size)
{
auto new_begin = data_allocator::allocate(size);
try
{
mystl::uninitialized_move(begin_, end_, new_begin);
}
catch (...)
{
data_allocator::deallocate(new_begin, size);
throw;
}
begin_ = new_begin;
end_ = begin_ + size;
cap_ = begin_ + size;
}

/*****************************************************************************************/
// 重载比较操作符

Expand Down

0 comments on commit 791617c

Please sign in to comment.