C++ 调用自定义»;析构函数&xAB;仅当包含对象的向量被删除时
向对象添加析构函数是一种方便的方法,可以确保它清除它可能分配的任何指针,而不依赖于程序员是否记得这样做 然而,当使用动态大小的向量时,向量有时会在向所述向量添加新对象时自动将所有对象移动到新位置(编辑:如果向量的大小超过分配的数据区域,则向量将其内容复制到新位置),导致在将所述对象的所有数据复制到新位置之后调用该对象的析构函数:C++ 调用自定义»;析构函数&xAB;仅当包含对象的向量被删除时,c++,oop,stdvector,C++,Oop,Stdvector,向对象添加析构函数是一种方便的方法,可以确保它清除它可能分配的任何指针,而不依赖于程序员是否记得这样做 然而,当使用动态大小的向量时,向量有时会在向所述向量添加新对象时自动将所有对象移动到新位置(编辑:如果向量的大小超过分配的数据区域,则向量将其内容复制到新位置),导致在将所述对象的所有数据复制到新位置之后调用该对象的析构函数: ... my_vector.push_back(my_object(...));//destructor of all my_objects before this n
...
my_vector.push_back(my_object(...));//destructor of all my_objects before this newly added one may just have been called
...
这基本上不是问题,因为所有数据都被复制,但如果相关对象在其析构函数中删除指针指向的对象或数组,或者以任何其他方式取消分配一些加载的数据,则可能会出现问题,例如,删除openGL纹理、缓冲区或着色器:
...
~my_object()
{
delete[] myArray;
delete myPointer;
glDeleteTexture(myTexture);
//the pointers and texture location may have been copied to the new location, but the data to which they point have been deleted
}
...
my_vector.push_back(my_object(...));//destructor of all my_objects before this newly added one may just have been called - myPointer, myArray and myTexture now point to no data
...
现在,向量中的旧对象(已复制到新位置)没有指向任何数据,这将是一个问题。
当然,这个问题可以通过添加自定义的unassign
函数来解决,该函数在删除整个向量时手动调用:
...
~my_object()
{
}
void unassign()
{
delete[] myArray;
delete myPointer;
glDeleteTexture(myTexture);
//the pointers and texture location may have been copied to the new location, but the data to which they point have been deleted
}
...
my_vector.push_back(my_object(...));//destructor of all my_objects before this newly added one may just have been called - nevermind
...
for (my_object& M: my_vector) M.unassign();//if this line is not forgotten everything is now unassigned
...
然而,问题是,当我使用这种方法时,我经常忘记调用这个unassign函数,留下指向对象的指针、指向数组和OpenGL纹理的指针、缓冲区和程序没有被删除
因此,我的问题是,是否有可能对对象进行编程,使其在删除整个向量时删除指针、纹理或任何类似数据,但不需要程序员记住添加特定行“可以对对象进行编程,使其在删除整个向量时删除指针、纹理或任何类似数据”
不,物体不知道它们在向量中,更不用说向量发生了什么
这也不相关。每当对象本身被销毁时,对象应该销毁其成员。这听起来可能很浪费,但由于移动操作,这可能非常便宜。std::vector
将调用您的移动构造函数来创建一个新对象,当vector知道它以后将销毁旧对象时。您可以利用通过窃取旧对象的成员来实现这一点,因此当旧对象被销毁时,它会发现自己没有成员
显然,这只适用于你可以窃取的成员。你只需复制一个普通的
int
向量,有时会自动将所有对象移动到一个新位置
这很令人担忧。你怎么会认为它在这样做呢?确保你遵循了“3的规则”(或5或零);如果您有正确的复制/移动构造函数,那么您所描述的应该不是问题。您可能不遵守my_object
的5/3/0规则。然后创建一个基类,其中包含一个GLuint-或uintptr\u t-handle,其中实现了move方法并删除了copy方法(只需复制句柄并将原始句柄设置为零,表示句柄为空。不要忘记将move操作符=声明为noexcept)。派生类随后可以创建和释放opengl对象,而无需担心移动/复制。这就是移动构造函数/赋值运算符发挥作用的地方。如果您有一个不可真正复制的类,则可以移动它,并将移动的类设置为空但可删除的状态。