C++是删除[]足够清理数组之后?
在下面的代码中,我使用new关键字动态分配数组。在超出作用域之前,我在数组上调用delete[],然后将punter设置为null 我的问题是,如果这足够的话,将删除[]以确保为数组中的所有3个Car对象分配的内存都已释放。还是我必须做一些特定的事情来释放每个对象使用的内存C++是删除[]足够清理数组之后?,c++,arrays,pointers,dynamic-memory-allocation,C++,Arrays,Pointers,Dynamic Memory Allocation,在下面的代码中,我使用new关键字动态分配数组。在超出作用域之前,我在数组上调用delete[],然后将punter设置为null 我的问题是,如果这足够的话,将删除[]以确保为数组中的所有3个Car对象分配的内存都已释放。还是我必须做一些特定的事情来释放每个对象使用的内存 void main() { Car * myArray = new Car[]{ * new Car("BMW"),*new Car("AUDI"), * new Car("SKODA") }; delet
void main()
{
Car * myArray = new Car[]{ * new Car("BMW"),*new Car("AUDI"), * new Car("SKODA") };
delete[] myArray;
myArray = nullptr;
}
另外,汽车类看起来像这样。在这里将名称设置为null也足够了吗。Name是一个字符指针。或者,可能不需要将指针设置为null,因为它没有引用堆上的任何内容
Car::Car(char * newName)
{
name = newName;
}
Car::~Car()
{
name = nullptr;
}
编辑:
首先,感谢所有精彩的回答和评论。我从阅读中学到了很多
现在我明白了,在声明动态分配数组时需要指定一个大小
除此之外,我也明白,我需要停止使用新的,因为我做。我想最好是将对象扔到堆栈上,然后让它们在某个点超出范围。除此之外,我猜我车上的破坏器什么也没用
阅读评论和答案后,我将代码更改为:
int main()
{
Car * myArray = new Car[3]{ Car("BMW"), Car("AUDI"), Car("SKODA") };
delete[] myArray;
myArray = nullptr;
}
在您的情况下,您已经从对new CarBMW的调用中泄漏了内存,并且丢失了能够释放内存的指针 这一行:
Car * myArray = new Car[]{ * new Car("BMW"),*new Car("AUDI"), * new Car("SKODA") };
创建一个包含3个汽车对象的数组,然后为每个条目创建一个新的汽车对象,使用它初始化数组中的对象,然后忘记新对象
可以更简单地这样写:
Car * myArray = new Car[3]{ Car("BMW"), Car("AUDI"), Car("SKODA") };
甚至
Car * myArray = new Car[3]{ "BMW", "AUDI", "SKODA" };
在这种情况下,您的delete[]足以释放所使用的内存
注意
Car::~Car()
{
name = nullptr;
}
不做任何事情来释放内存。一旦调用了汽车析构函数,任何人都不应该再次访问该对象的名称——事实上,它是未定义的行为,所以将其设置为null没有什么意义
编辑注:正如R Sahu和Aslak Berby所指出的,Car*myArray=newcar[]{…};不是生成数组的有效方法,请使用Car*myArray=new Car[3]{…};相反。是的,只有在创建Car元素的普通数组时才足够,因为数组名称是指向其第一个元素的指针 您通过指定[]来通知编译器它是一个数组 在您的例子中,您似乎正在创建汽车指针,因此您必须清理每辆汽车占用的内存位置,然后清理为整个阵列分配的内存 你错误地尝试这样做,但不要这样做。它很复杂
Car** cararrptr = new Car*[3];
cararrptr[0] = new Car("win");
cararrptr[1] = new Car("lin");
cararrptr[2] = new Car("ios");
//now to clean up
delete cararrptr[0];
delete cararrptr[1];
delete cararrptr[2];
delete[] cararrptr;
看看这个讨论
您不能使用:
Car * myArray = new Car[]{ * new Car("BMW"),*new Car("AUDI"), * new Car("SKODA") };
您需要指定一个大小
Car * myArray = new Car[3]{ * new Car("BMW"),*new Car("AUDI"), * new Car("SKODA") };
即使在那之后,打电话
delete [] myArrary;
将会泄漏内存。这条线相当于:
Car * myArray = new Car[3];
Car* car1 = new Car("BMW");
Car* car2 = new Car("AUDI");
Car* car3 = new Car("SKODA");
myArray[0] = *car1;
myArray[1] = *car2;
myArray[2] = *car3;
线路
delete [] myArrary;
不删除分别为car1、car2和car3分配的对象。你也必须明确地删除它们
delete car3;
delete car2;
delete car1;
但是,您不能使用
Car * myArray = new Car[3];
因为Car没有默认构造函数。您可以向Car添加默认构造函数。否则,您可以使用:
Car * myArray = new Car[3]{ Car("BMW"), Car("AUDI"), Car("SKODA") };
那么,使用以下各项就足够了:
delete [] myArrary;
取消分配内存。基本上,对于每个新的内存,您需要一个delete或delete[]。但在更复杂的程序中,这可能非常困难,并且容易出错
你应该学会使用像或这样的智能指针,而不是原始指针。在大多数情况下,这样可以避免显式的新建和删除
Car * myArray = new Car[X];
此代码已创建X个汽车对象。你所要做的就是真正地使用它们
然而,我认为你的困惑在于:这是另一种方法
Car ** myArray = new Car*[3] { new Car("BMW"), new Car("AUDI"), new Car("SKODA") };
for (int i = 0; i < 3; i++)
delete myArray[i];
delete[] myArray;
此代码分配一个由3个Car*指针组成的数组。因此,您还没有创建任何Car对象,这就是为什么您使用新的Car调用初始化每个Car*指针,这实际上创建了Car对象。我同意您使用关键字new太多的评论 我建议改用std::vector 下面是一个工作示例,其中类Garage在heap/freestore上有一个Car向量,然后使用析构函数~Garage将其删除 示例仅用于说明:
class Car {
Car();
string m_name;
public:
Car(const string &);
void print();
};
Car::Car(const string &s) : m_name{s} { }
void Car::print()
{
cout << m_name << endl;
}
class Garage {
string m_name;
vector<Car> *m_cars; // for allocating on heap
public:
Garage(const string &);
~Garage();
void add(const Car &);
void print();
};
// Creating a new vector on heap
Garage::Garage(const string &s) : m_name{s}, m_cars{new vector<Car>} { }
Garage::~Garage()
{
delete m_cars; // deleting the vector.
}
void Garage::add(const Car &c)
{
m_cars->push_back(c);
}
void Garage::print()
{
for (auto car : *m_cars)
car.print();
}
int main()
{
Garage garage{"Luxury garage"};
garage.add(Car("BMW"));
garage.add(Car("Audi"));
garage.add(Car("Skoda"));
garage.print();
}
使用上面的新向量仅用于演示,不需要。使用没有新的std::vector可以更快、更安全地实现这一目的,并且在使用后不需要删除它
也可以考虑使用智能指针,而不是使用NeX.
。可以将对象添加到堆或堆栈中。如果您将其添加到堆中,则可以动态创建它。这是使用new完成的,您将得到一个指针作为回报
Car *aCar=new Car("BMW");
如果在堆栈上创建它,则只需像使用其他变量一样定义它
Car anotherCar("BMW");
如果在堆上创建它,还需要从堆中取消分配它。这是用delete完成的
delete aCar;
您从未解除分配在堆栈上创建的对象。当您超出范围时,它将自动解除分配
至于创建数组,您可以创建statick或DynamicCall对象的数组
动态:
Car **cars=new Car*[3];
cars[0]=new Car("BMW");
cars[1]=new Car ....
所有这些都需要删除
当然。这里没有层叠
delete cars[0];
delete cars[1];
// And finaly the array.
delete[] cars;
您可以通过以下方式创建它们:
Car cars[]={"BWM", "AUDI"};
这一次,包括数组在内的所有对象都被推送到堆栈中,并且在超出范围时将被删除
在这两者之间,您可以创建一个基于堆栈的数组,指向堆分配的对象,或者一个heaplocated静态数组,正如这里的其他建议一样
<> P>关于C++,我建议使用STD::库,在这种情况下,STD::向量;
要么:
std::vector<Car *> myArray;
myArray.push_back(new Car("BMW"));
.....
// Cleanup:
for(auto car : myArray)
delete car;
或:
我不知道我怎么会在这里工作了两年。没有一个答案能给出一个简单的C++解决方案,所以这里是一个使用容器的60秒解决方案,并且没有新的/删除的。
#include <iostream>
#include <string>
#include <vector>
struct Car {
// Allows implicit conversion from char *
Car(const char *manufacturer) : manufacturer_(manufacturer) {}
std::string manufacturer_;
};
int main() {
std::vector<Car> cars{ "BMW", "AUDI", "SKODA" };
for (const auto& car : cars) {
std::cout << car.manufacturer_ << "\n";
}
}
否。删除[]myArray只会导致一个称为悬空指针的东西
这基本上意味着程序不再拥有指向的内存
myArray,但myArray仍然指向该内存
为了避免指针悬空,删除后将指针分配给nullptr
删除[]myArray
myArray=nullptr 你用新方法太多了。几乎没有理由去做新的事情。不要。说真的,别这样。现在,忘了你曾经听说过新的。你不需要它,也不想要它。新表达式的数组形式尤其糟糕,即使在将来确实需要使用new的情况下,也不应该使用new数组。如果需要动态数组,请使用std::vector。如果您不太可能需要动态指针数组,请查找Boost和/或使用向量。哦,main返回一个int。你使用的指针太多了。下面是一个例子,在堆/空闲存储上创建一个向量,然后使用析构函数将其删除:在指针超出范围之前将其设置为null没有任何用处。Car*myArray=new Car[3];这不会在第一时间编译,因为OP没有为Carthat定义默认构造函数,因为OP应该做一些不同的事情。添加了更多的代码来澄清我的答案,效果更好。剩下的唯一问题是数组不是指针,但这太离题了,在这里无关紧要。关于这个主题的阅读很好:左边是数组不是指针,我最好不要试图解释你在这里要说的。工作得更好我从来没有改进过任何代码让它工作得更好。这是我写的唯一一个片段,当然它是有效的。new std::vector是如此错误,请不要这样做。你正朝着正确的方向迈出一步,所以请保持std::vector。然后你甚至不需要定义析构函数。@stefan是的,你是对的,但它只用于演示特别是作为初学者的演示,在示例代码附近没有新代码是很有价值的-Car*myArray=new Car[]{*new Car..充其量是指向指针数组的指针。这意味着Car*myArray首先是错误的。此外,我认为您不能以这种方式静态分配具有动态创建内容的对象数组。您必须先创建数组,然后创建元素。Car**myArray=new Car**[3];myArray[0]=new CarBMW;…@AslakBerby:这毫无意义。Car*myArray是指向一辆或多辆车的指针,而不是指向指针的指针。new Car[]创建一个车数组,而不是指针数组。而*new CarBMW是一个车对象,不是指针。这也是内存泄漏,但这与此无关。@mAlter构造new Car[n]创建一个Car数组。new Car[]={new Car}是非法的,但在我的头脑中是指向指针的指针。正确的语法应该是Car*myArray[]={new CarBMW,…};@AslakBerby:都是真的,但你的第一个评论是关于一个不同的形式,它实际上不是指向指针数组的指针。@MSalters:我看到我解释得很糟糕。
#include <iostream>
#include <string>
#include <vector>
struct Car {
// Allows implicit conversion from char *
Car(const char *manufacturer) : manufacturer_(manufacturer) {}
std::string manufacturer_;
};
int main() {
std::vector<Car> cars{ "BMW", "AUDI", "SKODA" };
for (const auto& car : cars) {
std::cout << car.manufacturer_ << "\n";
}
}