c++ - vector 如何在减小其大小后不破坏元素两次?

标签 c++ resize stdvector destruction

出于测试目的,我试图创建自己的 vector 类,但我无法弄清楚 std::vector 大小缩减是如何工作的。

class A
{
    A()
    { std::cout << "A constructed") << std::endl; }
    ~A()
    { std::cout << "A destroyed") << std::endl; }
}

main()
{
    std::vector<A> vec(3, A());
    vec.resize(2);
    std::cout << "vector resized" << std::endl;
}

输出为

A constructed       (1)
A constructed       (2)
A constructed       (3)
A destroyed         (1)
Vector resized
A destroyed         (2)
A destroyed         (3)

vec.resize(2)被调用时,第三个元素被销毁,但是 vector 的容量仍然是3。然后当vec被销毁时,它的所有元素包括已经销毁的元素在内的元素都应该被销毁。 std::vector 如何知道他已经销毁了该元素?如何在我的 vector 类中实现它?

最佳答案

容量和大小之间存在差异。给定 std::vector<T> v;该 vector 已为 v.capacity() 分配了内存。元素。但仅限于第一个v.size()地方包含构造T对象。

所以,v.reserve(1000)在空 vector 上不会调用任何额外的构造函数。 vec.resize(2)在你的例子中破坏了最后一个元素和 vec[2]现在内存中是空的,但内存仍然属于 vec

我认为你的分配看起来像 buffer = new T[newSize]; 。不是这样std::vector不允许的作品 Ts没有默认构造函数。也许你没有意识到这一点,但是每当你获得一 block 内存时,它已经包含了对象,让它成为 T x;甚至 new double[newSize];它返回一个 double 组(尽管它们的构造函数是空的)。

在 C++ 中获取可用的未初始化内存只有一种方法,那就是分配 chars 。这是由于strict aliasing rule.还有(是|必须)一种如何在此内存上显式调用构造函数的方法,即如何在那里创建对象。该 vector 使用名为 placement new 的东西。正是这样做的。那么分配就是 buffer = new char[newSize*sizeof(T)];它不会创建任何对象。

对象的生命周期由该放置 new 运算符和对析构函数的显式调用来管理。 emplace_back(arg1,arg2)可以实现为 {new(buffer + size) T(arg1,arg2);++size;} 。请注意,只需执行 buffer[size]=T(arg1,arg2);不正确,UB。 operator=预计左侧尺寸 ( *this ) 已经存在。

如果你想用例如销毁一个对象pop_back ,你必须做 buffer[size].~T();--size; 。这是极少数应该显式调用析构函数的地方之一。

关于c++ - vector 如何在减小其大小后不破坏元素两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56908735/

相关文章:

c++ - 是否有库函数来确定 IP 地址(IPv4 和 IPv6)在 C/C++ 中是私有(private)的还是本地的?

c++ - 如何在 GCC 中使用 c++20 模块?

python - 如何修复 kivy 游戏的宽高比?

当子div高度改变时Jquery自动展开父div

c++ - 尝试用 C++ 编写一个只读取第一列数据并跳到下一行的类

c++ - 将 std::vector 分配给方法内的指针

c++ - 如何检测 Windows 是否正在关闭或重新启动

android - 如何从 AAssetManager 获取 std::basic_istream?

javascript - 如何禁用 _moz_resizing?

c++ - 当数据包含空格时,如何将制表符分隔文件的内容加载到 C++ 中的二维字符串 vector 中?