向量类中擦除函数的正确实现是什么
What is the correct implementation of erase function in vector class
我正在尝试在不使用迭代器的情况下实现我自己版本的向量类。以下是这个问题可能需要的部分。
template <typename T>
class Vector {
public:
...
~Vector()
{
delete [] m_data;
}
...
void erase(size_t position)
{
if (position >= m_size) {
throw std::out_of_range("erasing an element out of bounds");
}
--m_size;
for (size_t i = position; i < m_size; ++i) {
m_data[i] = m_data[i + 1];
}
m_data[m_size].T::~T();
}
...
private:
T* m_data;
size_t m_size;
...
};
以下是cplusplus.com对std::vector
的erase
函数的引用:
这有效地通过移除元素的数量来减少向量大小,在之前调用每个元素的析构函数。
因此,我试图通过调用最后一个重复元素的析构函数来实现相同的功能。m_data[position]
的析构函数是不必要的,因为它将被下一个元素所取代。
问题是向量类delete [] m_data
的析构函数中的代码也会为每个元素调用析构函数,这将导致内存的双重删除和崩溃。
有人能帮我为向量类写正确的擦除函数吗?
你正在尝试的不会那么容易!如果你想实现类似std::vector<T>
的东西,你需要做完整的工作:你需要处理原始内存并显式地构造/销毁对象。也就是说,您需要分配足够的未初始化内存块,根据需要在适当的位置构造/销毁对象,并最终释放分配的内存。对于玩具版的std::vector<T>
来说,这是一个有趣的练习,然后您会很乐意将版本随编译器一起使用,因为它在某种程度上更快,实际上实现了所有功能,并且相当无错误。当然,如果您碰巧实现了标准C++库的一个版本,那么您将需要经历整个练习。好消息是:与std::deque<T>
相比,std::vector<T>
微不足道,我敢打赌,如果不使用算法,你将无法获得与标准库版本一样高效的版本(要想真正有效地实现这一点,还需要相当复杂的算法版本;我不确定是否有许多实现真正实现了std::deque<T>
上的专业版本)。
顺便说一句,不使用迭代器是没有帮助的:像std::move()
(以迭代器为参数的版本)或std::copy()
(如果你不使用C++2011)这样的算法可以避免代码中出现重复版本。将代码放入算法中还有一个额外的优势,即它们不是完全琐碎的逻辑,而是根据需要很好地封装的。将重复需要的代码放入算法中会使容器的实现相对简单,从而使实现更有可能正确。。。更不用说实现有趣的优化实际上也是可行的。
您想要的是生成char数组。
然后,您可以使用placementnew将元素放入向量中,并在删除元素时显式调用析构函数。
void push_back(T const& el)
{
makeSureThereIsSpaceForOneMore();
new (&E[m_size]) T(el);
++m_size;
}
void erase(size_t index)
{
MoveStuffAround();
E(index)->~T();
--m_size;
}
private:
char* m_data;
size_t m_size;
...
T* E(size_t index){return reinterpret_cast<T*>(&m_data[index * sizeof(T)]);}
};
@Artak别忘了检查另一个方向(擦除)的边界
用m_data[m_size] = T();
替换m_data[m_size].T::~T();
怎么样?
我提出了一个解决方案,不使用new/delete
运算符,而是使用C样式的malloc/free
。这是因为new
和delete
运算符隐式调用构造函数和析构函数,而您无法控制它们。相反,如果我们使用malloc/free
,那么当我们需要时,我们可以显式地调用对象的构造函数/描述符
因此,在这个例子中,我们可以显式地调用erase
函数中最后一个对象的析构函数,也可以显式调用向量类的解构函数中的每个元素的析构因子。
- 实现无开销push_back的最佳方法是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 是什么原因导致它无法编译?它是声明签名还是在函数本身的实现中
- 私有在函数定义/实现的返回值范围内是什么意思 (c++)?
- 在 c++ 或 python 中生成一个体面的视差图以在 Raspberry Pi 上实现的最佳方法(算法或函数)是什么
- 在 C++17 中实现迭代器和const_iterator的正确方法是什么?
- 十进制到二进制的实现不能完全适用于我大学的检查器。问题或提示可能是什么
- 实现此自定义priority_queue的正确方法是什么
- 实现此"on error, throw"回调的最佳方法是什么?
- 在QGraphicsView上实现交互式样条曲线的最佳方法是什么?
- 当您知道结构将来会更改时,实现结构读写的最佳方法是什么
- std :: is_nothrow_copy_copy_constructible的实现是什么?
- 具有多态数据的容器的常见实现是什么
- RWTPtrOrderedVector的替代实现是什么
- 将一元函数应用于向量的某些元素的良好实现是什么?
- 向量类中擦除函数的正确实现是什么
- 映射到ASCII的Character的底层实现是什么?
- c++中标准的延迟/终结器实现是什么?
- 访问和更改长布尔数组的最快实现是什么?
- 单例类的确切用法和实现是什么?