std::vector 在清除或删除 POD 时的行为是不是不同

Posted

技术标签:

【中文标题】std::vector 在清除或删除 POD 时的行为是不是不同【英文标题】:Does std::vector behave different for clearing or deleting PODsstd::vector 在清除或删除 POD 时的行为是否不同 【发布时间】:2016-11-29 08:49:04 【问题描述】:

我正在尝试理解 std::vector,并且我知道如果 vector 是包含用户定义类的向量,那么在该类拥有资源的“所有权”时调用其析构函数很重要。在这种情况下,我想它会遍历每个元素并在每个元素上调用析构函数。

但是对于普通的旧数据,我认为不需要调用析构函数,只需简单地删除整个块。如果我不得不猜测,我会说重新分配会更快。

实现你自己的数组类来区分这两者并根据需要做的不同表现会相当容易吗?谢谢。

【问题讨论】:

你所说的“清晰”是什么意思?向量何时或为什么需要“清除”其数据?您能否展示一些代码来说明您的问题和您遇到的问题?最重要的是,这只是好奇心还是您想要解决的实际问题?那么实际问题是什么? 没有std::is_pod 就不容易区分了。标准库实现者不需要执行此检查。但如果流行的不这样做,我会感到惊讶。 如果我正确地解决了您的问题,您会问“我可以在使用 POD 清除或初始化时只使用 std::vector memset 吗?”。这不是非常 C++ 的做事方式,因为如果您稍后添加一个将您的类型转换为非 pod 的成员,您可能会破坏事情。 @Some 程序员老兄 我所说的“清除”是指调用 clear() 函数,或者说它超出范围并需要释放内存块。抱歉,不,没有实际的“问题”,我只是想了解例如 vector 是否可能有两个不同的模板版本,具体取决于它是否包含 POD 或带有析构函数的对象等,我' @Marco A. 我问的是如果 POD 不需要调用析构函数,那么循环遍历每个元素并删除它不是必需的,只需要清除整个块.我不是说自己调用 memset,只是想知道 std::vector 是否区分两者。 【参考方案1】:

来自 gcc 向量实现:

void
clear()
 _M_erase_at_end(this->_M_impl._M_start); 

所以,clear 调用受保护的函数_M_erase_at_end,让我们看一下:

void
_M_erase_at_end(pointer __pos)

    std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
    this->_M_impl._M_finish = __pos;

它从向量的开头(__pos 开始)到结尾调用 std::_Destroy。

template<typename _ForwardIterator, typename _Allocator>
void
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
     _Allocator& __alloc)

typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
for (; __first != __last; ++__first)
__traits::destroy(__alloc, std::__addressof(*__first));

因此,它在整个内部数组中进行迭代并调用 __traits::destroy,而不是一次释放所有内存块。

编辑:你写了But it would seem when clearing vector that it does call delete on its elements - 答案是大不。 STL 容器不拥有外部分配的内存,您必须始终调用 delete 或使用 shared\unique_ptr 否则会泄漏。

【讨论】:

我知道指针向量不会释放指针指向的内存。那么vector不区分指向类型和类型的指针吗?似乎对vector的每个元素都调用了delete,而不是vector,我认为这将是一个泄漏。

以上是关于std::vector 在清除或删除 POD 时的行为是不是不同的主要内容,如果未能解决你的问题,请参考以下文章

C++ STD 容器:std::vector - 有没有办法清除向量并保留存储分配?

启用 C++11 时的 std::vector 性能回归

是否需要清除 STL 向量

将 std::vector 与类一起使用时的 C++ 读写问题

序列化 std::vector 以提升二进制存档时的数据相关失败

声明变量以保存字符串列表时的内存分配