在C ++中,让我们说我正在创建一个指针数组,每个元素应该指向一个数据类型MyType。我想在函数fillArPtr(MyType *arPtr[])
中填充此数组。让我们说我可以使用函数createObject(int x)
创建MyType对象。它的工作方式如下:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
这是最好的方法吗?在这个程序中,我应该如何使用delete删除由“new”创建的对象(或者我应该使用delete?)
答案 0 :(得分:1)
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
我建议你研究一下boost shared_ptr
(也在TR1库中)
已经好多了:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
为明星拍摄:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
答案 1 :(得分:1)
既然你问过“最好的方法是什么”,那么让我来看看这个问题并提出更多类似C ++的选择。由于您的createObject
已经按值返回对象,因此以下内容应该有效:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
现在您根本不需要进行任何内存管理,因为分配和清理是由vector类完成的。像这样使用它:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
但是,如果您对手动内存管理和指针有真正的要求,但最好是使用示例。
答案 2 :(得分:0)
你基本上会遍历数组的每个元素并在其上调用delete,然后将元素设置为0或null。
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
另一种方法是使用std :: vector。
答案 3 :(得分:0)
如果您不必在任何地方返回数组,请使用auto_ptrs数组。只要您不制作auto_ptrs的副本,它们就不会更改所有权,并且自退出RAII以来,它们将在退出函数时释放其资源。它也已经是标准的一部分了,所以不需要使用它来提升:)它们在大多数地方都没用,但这听起来不错。
答案 4 :(得分:0)
您可以使用delete objPtr
删除已分配的对象。在你的情况下,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
要记住的经验法则是,如果使用new
分配对象,则应delete
。如果使用new[N]
分配对象数组,则必须delete[]
。
不要将指针粘贴到原始数组中,而是查看std::array
或std::vector
。如果您还使用智能指针(例如std::unique_ptr
)来保存std::array
内的对象,则无需担心删除它们。
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
完成使用后,您无需担心删除它们。
使用createObject(int x)
的{{1}}函数是否可以创建对象并返回指向此的指针?在这种情况下,您还需要删除它,因为在此声明中
new
您正在制作new MyType( createObject(i++) )
返回的对象的副本,但原件会被泄露。如果您同时更改createObject
以返回createObject
而不是原始指针,则可以防止泄漏。
如果std::unique_ptr<MyType>
正在堆栈上创建对象并按值返回它们,则上述内容应该可以正常工作。
如果createObject
没有使用createObject
来创建对象,而是在堆栈上创建它们并返回指向这些对象的指针,那么你的程序将无法正常工作,因为堆栈当new
退出时,对象将被销毁。
答案 5 :(得分:0)
您的方法将指针数组放在堆栈上,这很好。我想我会指出也可以存储你的指针数组on the heap。如果您希望阵列超出当前范围
,请执行此操作MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
如果这样做,请不要忘记从堆中删除数组本身
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
如果你打算使用vector,并且事先知道数组的大小,你应该预先调整数组的大小。你会得到更好的表现。
vector<MyType*> arr(10);