加速C++练习 11-6
Accelerated C++ exercise 11-6
11 个练习 11-6 中卡在擦除函数中。我已经销毁了对象,但我不知道如何使用分配器库中的释放来返回空间。
请保释我。PS :这不是家庭作业,但我在家练习
以下是来自加速C++的代码,之后是我修改的擦除功能。谢谢 '
template <class T> class Vec
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef size_t size_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
Vec() { create(); }
explicit Vec(size_type n, const T& t = T()) { create(n, t); }
Vec(const Vec& v) { create(v.begin(), v.end()); }
Vec& operator=(const Vec&);
~Vec() { uncreate(); }
T& operator[](size_type i) { return data[i]; }
const T& operator[](size_type i ) const { return data[i]; }
void push_back(const T& t)
{
if (avail == limit)
{
grow();
}
unchecked_append(t);
}
iterator erase(iterator);
iterator erase( iterator, iterator );
void clear();
size_type size() const { return avail - data; }
iterator begin() { return data; }
const iterator begin() const { return data; }
iterator end() { return avail; }
const iterator end() const { return avail; }
private:
iterator data;
iterator avail;
iterator limit;
std::allocator<T> alloc;
void create();
void create(size_type, const T&);
void create(const_iterator, const_iterator);
void uncreate();
void grow();
void unchecked_append(const T&);
};
我的代码
template <class T> typename Vec<T>::iterator Vec<T>::erase(iterator first, iterator second )
{
if( second < first )
{
throw std::out_of_range("Iterator out of bounds.");
}
if( first < data || second >= avail )
{
throw std::out_of_range("Iterator out of bounds.");
}
iterator last = avail -1 ;
iterator i = first ;
iterator j = second ;
while( j <= last )
{
*i++ = *j++ ;
}
// destroy each initilsed space
iterator new_avail = avail - first + second ;
std::cout << " end " << end() << std::endl;
while( avail != new_avail )
{
alloc.destroy(--avail ) ;
}
// dellocate space how to do that ?
alloc.deallocate( avail -1, ); // not sure what to do here
return first ;
}
不能解除分配已分配内存的一部分。那
alloc.deallocate( avail -1, (;
不好。
编辑
您不应尝试在擦除中管理分配。您有一个选择是重新分配它,这将使擦除更加贵。第二个函数可以执行以下操作:
iterator shrink(iterator first, iterator last) {
size_type capacity = (limit - data) - (last - first);
iterator new_data = alloc.allocate(capacity);
iterator new_avail = new_data;
iterator source = data;
while(source < first)
// C++11
alloc.construct(new_avail++, std::move(*source++));
source = last;
iterator result = new_avail;
while(source < avail)
// C++11
alloc.construct(new_avail++, std::move(*source++));
while(data < avail)
alloc.destroy(--avail);
data = new_data;
avail = new_avail;
limit = new_data + capacity;
return result;
}
更好的选择是这种标准方式。添加一个额外的构造函数, 交换和shrink_to_fit:
Vec(const_iterator first, const_iterator last) {
create(first, last);
}
void swap(Vec& other) {
std::swap(data, other.data);
...
}
bool shrink_to_fit() {
try
{
Vec(begin(), end()).swap(*this);
return true;
}
catch(...) {}
return false;
}
现在,您可以对向量应用多个操作并最终减少内存消耗。
v.erase(a, b);
v.erase(c, d);
...
v.shrink_to_fit();
我想,解决方案之一是创建一个具有以下大小的新向量:
new_size = old_size - number_of_elements_to_delete
然后,您将对象从开始复制到第一个擦除对象,从最后一个擦除对象复制到结束,然后释放旧矢量。
这不是最好的解决方案,而是我认为最简单的解决方案。
std::allocator::deallocate
的参考页面必须说的内容:
void deallocate( pointer p, size_type n );
解除分配指针
p
引用的存储,该存储必须是先前调用allocate()
获得的指针。参数n
必须等于最初生成p
的调用allocate()
的第二个参数。
也就是说,您不能解除分配的一部分存储,只能释放整个块。
解决方案是不返回通过调用erase
而获得的免费存储空间。只需相应地更新您的成员迭代器,以便您保持此存储可用于后续调用create
。这也是标准容器vector
的作用。
如果您确实想返回多余的存储,请分配一个较小的临时块,复制保留在容器中的元素,释放旧存储并更新迭代器。
这里要记住的是异常安全。分配临时缓冲区后,需要确保在复制元素期间发生异常时不会泄漏它。
正如jrok和其他人所提到的,你不能释放部分内存 - 你需要释放整个引用的存储。
还有一件更重要的事情 - 如果您浏览第 11 章(特别是 11.4 下的动态 Vecs(,您会注意到 push_back()
的实现一旦达到当前最大大小,底层数组的大小就会加倍。
在类似的行中,当向量的大小变为当前最大大小的四分之一时,您希望将基础数组的大小减半。此时需要重新分配内存并调用std::allocator::deallocate
以释放多余的存储空间。
- 加速C++练习2.4
- MSVC是否支持C++11样式的属性而不是__declspec
- 创建LinkedList退出,返回代码为-11(SIGSEGV)
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如何将模板转换为C++11之前的模板
- c++11评估顺序(未定义的行为)
- C++中的VLA,扩展名为std=C++11
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- "类模板示例<int>;"语句对 C++11 是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 如何使用lock_guard在c++11中实现scoped_lock功能
- C++11 中不同类型的对象的 std::array 的替代方案
- 为什么 -mmacosx-version-min=10.10 不阻止使用标记为从 10.11 开始的函数?
- 为什么我的C++代码中出现'Segmentation Fault: 11'行?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- C++ 独特指针练习的向量
- 斯特劳斯特鲁普 第四章 练习 11.
- 加速C++练习 11-6