c++ -对于一个指向对象的指针的矢量,重新分配是否会导致删除和复制对象?

时间:2022-07-10 17:00:17

From my understanding so far, if you have a vector of class objects, if you erase any member of the vector, typically the vector will reallocate some of it's objects in order to preserve memory contiguousness. Hence you need to implement the rule of three (destructor, copy constructor and copy assignment operator) for everything to be preserved when erasing vector members.

根据我目前的理解,如果你有一个类对象的向量,如果你擦除向量中的任何一个向量,通常这个向量会重新分配一些对象,以保持记忆的连续。因此,在删除向量成员时,您需要执行三个(析构函数、复制构造函数和复制赋值操作符)的规则。

However: for a vector of pointers to class objects the outcome is less clear to me. If I erase a member, then surely C++ is smart enough to just copy the pointers around - not maddeningly delete the pointer (and the class object it points to) then re-create it and the object it points to again?

然而,对于一个指向类对象的指针,结果不太清楚。如果我删除了一个成员,那么c++就足够聪明,只需要复制指针,而不是疯狂地删除指针(以及它指向的类对象),然后重新创建它,并再次指向它指向的对象?

If this is not the case, can someone explain this idiocy to me?

如果不是这样的话,有人能给我解释一下这个白痴吗?

2 个解决方案

#1


1  

The vector will delete, construct, and copy whatever type it contains. In the case of a vector of pointers to a class/structure, it will delete, construct, and copy pointers, leaving the actual objects the pointers point to alone. It is up to you to allocate and deallocate these.

vector将删除、构造和复制它包含的任何类型。在指向类/结构的指针的情况下,它将删除、构造和复制指针,将指针指向单独的对象。由您来分配和释放这些。


EDIT

An example:

一个例子:

If you have the following:

如果你有以下几点:

class A
{
  A() {}
}

void foo(void)
{
   A * pointerToA = new A;
}

At the end of the function foo's scope the only thing that is deallocated is the memory for the variable pointerToA itself, i.e. 4 bytes that hold an address (in 32 bit) - which in this case is stored on the stack. The only way that the memory allocated for a new instance of class A will be freed is if you manually call delete with the address to pointerToA.

在函数foo的范围结束时,唯一被释放的是变量pointerToA本身的内存,即4个字节(32位),在这个例子中存储在堆栈上。为a类的新实例分配内存的惟一方法是,如果您手动调用delete和pointerToA的地址。

Let's take the example of an array of class A

让我们以A类数组为例。

A ** arrayOfPointerToA = new A*[10];
for(unsigned i = 0; i < 10; ++i)
  arrayOfPointerToA[i] = new A;

which is similar to what happens when you have std::vector<A*>. When you call

这类似于std::vector 。当你打电话 *>

delete [] arrayOfPointerToA;

you're deallocating the memory for the array of pointers, not for each A.

您正在为指针数组分配内存,而不是为每一个A。

c++ -对于一个指向对象的指针的矢量,重新分配是否会导致删除和复制对象?

In the above diagram, the memory deallocated by the above call to delete is highlighted in red. Note that each A is stored at a random location in memory in this instance since they were all allocated separately.

在上面的图中,由上面的调用删除的内存释放被用红色突出显示。注意,在这个实例中,每个A都存储在内存中的一个随机位置,因为它们都是单独分配的。

Now taking this to a vector:

现在把它变成一个向量:

A std::vector<A> effectively uses new A[size] to allocate memory. If you're storing a raw pointer, this would mean it would allocate an array of type A, which means that size number of objects of type A are created. When the vector frees its memory size number of objects of type A are destroyed. Now take that example and replace A with A* and you'll see that no objects of type A are destroyed.

一个std::vector有效地使用了新的A[size]来分配内存。如果您正在存储一个原始指针,这将意味着它将分配a类型的数组,这意味着创建a类型的对象的大小。当向量释放它的内存大小时,A类型的对象被销毁。现在以这个例子替换A,你会看到A类型的对象没有被破坏。

This is a fundamental part of how C++ and pointers work, not just a property of containers. If containers did arbitrarily call delete on each member, this wouldn't make sense as when we have a container A we would call delete on an instance of an object instead of a pointer to that object which is not valid.

这是c++和指针工作的基本部分,而不仅仅是容器的属性。如果容器对每个成员都任意调用delete,这就没有意义了,因为当我们有一个容器a时,我们会调用一个对象实例的delete,而不是指向那个无效的对象的指针。

#2


1  

The vector will leave your pointer values alone. It of course will move the values in the internal array when you push, pop, or erase.

这个向量将保留指针值。它当然会在你推送、弹出或删除的时候移动内部数组中的值。

In this case the values are just pointers. But there is no logic in the vector to determine if something is a pointer to an object and delete/reallocate them when the values are copied.

在这种情况下,值就是指针。但是,在向量中没有逻辑来确定某个东西是否是对象的指针,并在复制值时将其删除/重新分配。

In the case of a vector that includes a complex type and not a pointer it will of course try to copy the values when the internal array is reallocated or moved.

对于包含复杂类型而不是指针的向量,当内部数组被重新分配或移动时,它当然会试着复制这些值。

#1


1  

The vector will delete, construct, and copy whatever type it contains. In the case of a vector of pointers to a class/structure, it will delete, construct, and copy pointers, leaving the actual objects the pointers point to alone. It is up to you to allocate and deallocate these.

vector将删除、构造和复制它包含的任何类型。在指向类/结构的指针的情况下,它将删除、构造和复制指针,将指针指向单独的对象。由您来分配和释放这些。


EDIT

An example:

一个例子:

If you have the following:

如果你有以下几点:

class A
{
  A() {}
}

void foo(void)
{
   A * pointerToA = new A;
}

At the end of the function foo's scope the only thing that is deallocated is the memory for the variable pointerToA itself, i.e. 4 bytes that hold an address (in 32 bit) - which in this case is stored on the stack. The only way that the memory allocated for a new instance of class A will be freed is if you manually call delete with the address to pointerToA.

在函数foo的范围结束时,唯一被释放的是变量pointerToA本身的内存,即4个字节(32位),在这个例子中存储在堆栈上。为a类的新实例分配内存的惟一方法是,如果您手动调用delete和pointerToA的地址。

Let's take the example of an array of class A

让我们以A类数组为例。

A ** arrayOfPointerToA = new A*[10];
for(unsigned i = 0; i < 10; ++i)
  arrayOfPointerToA[i] = new A;

which is similar to what happens when you have std::vector<A*>. When you call

这类似于std::vector 。当你打电话 *>

delete [] arrayOfPointerToA;

you're deallocating the memory for the array of pointers, not for each A.

您正在为指针数组分配内存,而不是为每一个A。

c++ -对于一个指向对象的指针的矢量,重新分配是否会导致删除和复制对象?

In the above diagram, the memory deallocated by the above call to delete is highlighted in red. Note that each A is stored at a random location in memory in this instance since they were all allocated separately.

在上面的图中,由上面的调用删除的内存释放被用红色突出显示。注意,在这个实例中,每个A都存储在内存中的一个随机位置,因为它们都是单独分配的。

Now taking this to a vector:

现在把它变成一个向量:

A std::vector<A> effectively uses new A[size] to allocate memory. If you're storing a raw pointer, this would mean it would allocate an array of type A, which means that size number of objects of type A are created. When the vector frees its memory size number of objects of type A are destroyed. Now take that example and replace A with A* and you'll see that no objects of type A are destroyed.

一个std::vector有效地使用了新的A[size]来分配内存。如果您正在存储一个原始指针,这将意味着它将分配a类型的数组,这意味着创建a类型的对象的大小。当向量释放它的内存大小时,A类型的对象被销毁。现在以这个例子替换A,你会看到A类型的对象没有被破坏。

This is a fundamental part of how C++ and pointers work, not just a property of containers. If containers did arbitrarily call delete on each member, this wouldn't make sense as when we have a container A we would call delete on an instance of an object instead of a pointer to that object which is not valid.

这是c++和指针工作的基本部分,而不仅仅是容器的属性。如果容器对每个成员都任意调用delete,这就没有意义了,因为当我们有一个容器a时,我们会调用一个对象实例的delete,而不是指向那个无效的对象的指针。

#2


1  

The vector will leave your pointer values alone. It of course will move the values in the internal array when you push, pop, or erase.

这个向量将保留指针值。它当然会在你推送、弹出或删除的时候移动内部数组中的值。

In this case the values are just pointers. But there is no logic in the vector to determine if something is a pointer to an object and delete/reallocate them when the values are copied.

在这种情况下,值就是指针。但是,在向量中没有逻辑来确定某个东西是否是对象的指针,并在复制值时将其删除/重新分配。

In the case of a vector that includes a complex type and not a pointer it will of course try to copy the values when the internal array is reallocated or moved.

对于包含复杂类型而不是指针的向量,当内部数组被重新分配或移动时,它当然会试着复制这些值。