矢量减小元素的大小后,如何不会破坏元素两次
How does vector not destroy element twice after reducing its size?
出于测试目的,我试图创建自己的向量类,而我无法弄清楚 std::vector
size younk yougn fors。
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)
时,第三个要素被销毁,但向量的容量仍然为3。然后,当vec
被销毁时,其所有元素包括已经被销毁的元素都应被销毁。std::vector
如何知道他已经破坏了该元素?如何在我的矢量类中实现?
容量和大小之间存在差异。给定std::vector<T> v;
,向量已为v.capacity()
元素分配了内存。但是只有在第一个v.size()
的位置中包含构造的T
对象。
因此,空矢量上的v.reserve(1000)
不会调用任何其他构造函数。vec.resize(2)
在您的示例中破坏了最后一个元素,而vec[2]
现在是内存中空的位置,但存储器仍然由vec
拥有。
我认为您的分配看起来像buffer = new T[newSize];
。这不是std::vector
的工作方式,不允许没有默认构造函数的Ts
。也许您没有意识到这一点,但是每当您获得一块内存时,它已经包含对象,让它为T x;
,甚至是new double[newSize];
,它返回了双打阵列(尽管它们的构造函数是空的(。
只有一种方法可以在C 中获得可用的非初始化内存,即分配chars
。这是由于严格的别名规则。也(必须是((必须是(在此内存上明确调用构造函数的一种方法,即如何在此处创建对象。矢量使用了所谓的新位置,这正是这样做的。然后,分配是简单的buffer = new char[newSize*sizeof(T)];
,它不会创建任何对象。
对象的寿命由此放置的新操作员管理,并向驱动器进行明确调用。 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;
。这是您应该明确称呼驱动器的几个地方之一。
简单的答案是向量内部管理构造函数和破坏者调用,通常是通过使用Inplace Operator New and Operator删除方法。
弹出元素后,立即进行了描述,并且在存储器仍然可用,并且可能仍包含一些残余值,std :: vector本身知道仍然需要删除哪些元素,并且不会调用destructor再次。
当调用
vec.resize(2)
时,第三个元素被销毁,但向量的容量仍然为3。
是。capacity
是向量的内部数组可以物理上保持多少元素。size
是该数组中有多少元素实际上有效。收缩size
完全不会影响capacity
。
然后,当
vec
被销毁时,其所有元素包括已经被销毁的元素都应被销毁。
以前被摧毁并从数组中删除的第三个元素不会再次被摧毁。只有size
元素数量被破坏,而不是capacity
元素数量,就像您在想的那样。
std::vector
如何知道他已经破坏了该元素?
它分别跟踪size
和capacity
。当从数组中删除一个元素时,随后的元素将其向下移动数组,每个插槽将size
降低。
- g++的分段错误(在NaN上使用to_string两次时)
- 蛇在C++不会连续转两次
- 检查一个数组是否包含在另一个数组中,以相反的顺序,至少两次
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 我应该如何去缓解两次出现的cin?
- Realloc 两次无法在 Visual Studio 上运行
- 使用 getline(cin, var) 两次在进行字符串比较时会产生错误 (==)
- 为什么映射插入和 map.find() 的单次迭代比插入和 map.find() 的两次单独迭代慢得多
- C++析构函数调用两次,堆栈分配的复合对象
- 为什么参数在构造 std::thread 时移动两次
- Qt插槽调用了两次
- 做 std::用相同的unique_ptr移动两次
- C++两次定义相同的函数会导致错误
- 为什么具有静态存储持续时间的同一内联变量在包含在 VS2017 编译的两个翻译单元中时会构造和销毁两次
- 矢量减小元素的大小后,如何不会破坏元素两次
- 用3x3结构元素进行两次形态扩张,等于用6x6结构元素进行一次形态扩张
- 在同一 unix 套接字连接中读取元素两次时出错
- QXmlStreamReader.readNextStartElement()读取开始元素两次
- 自定义分配器- Microsoft std::map实现对相同的元素进行两次重新分配,GCC工作得很好
- 从向量中移除元素时,析构函数调用了两次