这是this question的扩展。我在网上搜索过但找不到满意的答案。
我有一个class A
,它定义了一个包含许多class Region
个实例的向量。这些Region
实例的内存处理需要由Class A
我的问题是:
1。在以下代码段中,是否需要在A类的desctuctor中显式删除这些实例?
2。我应该将实例创建为new Region(i)
吗?它是否比第一个选项更好(不使用new
)A类是一个相当大的对象。我该如何确定是否使用新的?
3. 如果对#2的回答是肯定的,我应该如何在析构函数中删除这些实例? delete Region(i)
(在for循环中)或delete [] reg
??我猜测以前的方式是正确的方法,但想确认一下。
4. 除了“区域实例未被删除”之外,您是否看到任何明显的内存泄漏...尤其是在A
的构造函数中构造Region对象时? / p>
class Region{
public:
Region(int num);
int number;
std::vector <elemt*> elements;
int info;
}
class A{
public:
std::vector<Region> reg;
const int numOfRegions = 100;
}
A::A(){
int i;
for ( i=0; i<numOfRegions; i++){
reg.push_back(Region(i));
}
}
A::~A(){
// How should the elements within vector Region be deleted??
// Should I use "new" to allocate memory to instances of Region()
}
更新 非常感谢所有回答的人!
答案 0 :(得分:3)
没有。 std::vector
将Region
存储为对象,并在添加/删除/覆盖元素时调用必要的(de)构造函数。
没有。仅当您将矢量声明为std::vector<Region *> reg;
时。如果Region是多态的,或者复制/赋值构造函数很昂贵(矢量经常复制元素),则必须这样做。
如果您将它们存储为指针,则需要迭代reg
并使用delete ptr;
删除每个元素。
根据您创建elemt
类实例的方式,您可能需要向Region
添加析构函数以销毁这些实例。
答案 1 :(得分:3)
在以下代码段中,我是否需要明确删除这些代码段 在课堂上的实例 ?A
不 - 它们会自动删除 - 如果您不使用new创建它,则不要删除它。
我应该将实例创建为新的Region(i)吗?是不是更好 第一个选项(不使用新的)A类 是一个很大的对象。我该怎么办? 确定是否使用新的?
A的大小不是问题。这个问题没有明确的答案,但一般规则是,如果你不必使用new动态创建对象,那么就不要这样做。
如果对#2的回答是肯定的,我应该如何删除这些实例 析构函数?删除区域(i)(在 for loop)或删除[] reg ??我是 猜测以前的方式是正确的 方式,但想确认。
如果您使用new创建它们,则可以在for循环中删除它们:
delete reg[i];
当然,reg必须是一个指针向量。更好的选择是使用智能指针向量。
除了“区域实例未被删除”之外,您是否看到任何明显的情况 内存泄漏..特别是在 A中Region对象的构造 构造
它们被删除 - 只是不是你。这被称为RAII,是非常非常好的C ++实践 - 你应该尽可能使用RAII。
答案 2 :(得分:1)
在class A
内,一切似乎都被定义好了。 (你需要整理课堂宣言)。这意味着当A的实例被销毁时,一切都将被自动销毁。是的,我的意思是std::vector reg;
会破坏自己,以及它负责的Region
个实例的所有副本。
你真的在问class Region
及其vector
哪个有指针,虽然你没有显示任何代码可能需要删除它的指针?
修改强>
(首先修改Region
的详细信息,第二次修改会删除它们并添加A::addRegions
)
我认为这就是你所追求的目标:
#include <vector>
class Region{
public:
Region(int num);
// Details of Region removed
};
class A{
std::vector<Region> reg;
const int numOfRegions;
public:
A();
// No destructor needed: ~A();
void addRegions(int num);
};
A::A():numOfRegions(100){
for (int i=0; i<numOfRegions; ++i){
reg.push_back(Region(i));
}
}
void A::addRegions(int num)
{
for (int i=0; i<num; ++i){
reg.push_back(Region(i));
}
}
注意class A
没有析构函数。
新强>
A::addRegions
也使用push_back
,即使现在也不需要析构函数。
还要注意类声明如何在它们之后有分号,并且A的构造函数初始化numOfRegions
。
答案 3 :(得分:1)
1。在您的示例中,您唯一需要明确删除的是elemt*
,如果它们是动态分配的。如果是这样,必须通过拥有它们来删除它们。如果您的Region
仅指向它们,则不应在其析构函数中删除它们。
2。首先,您的向量在堆栈中分配,并且将被解除分配而不会出现问题。其次,要使用new Region(i)
,您需要更改class A
声明。但在你的情况下,没有必要这样做。您应该使用operator new
的几个示例:
1)需要更持久的数据,因为动态分配的数据将持续存在,直到明确解除分配(并且只要保持指针指向它就可以访问)
2)您的对象可能太大而无法全部存储在堆栈中。
3。如果您确实使用了new Region(i)
,那么您可能会在某些时候使用operator delete
(可能是在析构函数或其他清理函数上)来正确释放它。
4。只有在elemt
向量中直接创建新的elements
时,您的构造函数才会出现问题,例如elements.push_back(new elemt())
。这是一种危险的设计,可能会导致多次内存泄漏或出现seg故障的风险。如果你想以这种方式分配它们,你需要一个支持复制机制的智能指针,如shared pointer
。