我是C ++的新手,我发现我被Java和更新的编程语言(如Swift)所破坏。所以我理解有时候你必须在C ++中手动删除对象,比如指针。您可以使用delete
关键字,也可以使用智能指针。但我对是否删除指针本身感到困惑,因此无法再次指向指针或删除指针指向的位置。
我正在编写充当整数链表的代码。所以我有一个指针指向列表的头部和尾部。当某人“轮询”某事时,应将其从列表中删除,然后相应地重置头部(或尾部)。所以我有一些代码可以正常工作:
int IntegerLinkedList::pollFirst(){
if (tail == nullptr && head == nullptr) {
return 0;
} else if (head == tail) {
int ret = head->getData();
head = nullptr;
tail = nullptr;
//delete head;
//delete tail;
return ret;
} else {
IntegerNode* newHead = head->getNext();
head->setNext(nullptr);
newHead->setPrevious(nullptr);
int ret = head->getData();
//delete head;
head = newHead;
return ret;
}
}
但是我从来没有真正删除它指向的对象,我只是删除它的所有指针。这会像在Java中那样删除对象吗?或者我必须手动删除它,我该怎么做?我记忆力泄漏了吗?非常感谢
更新头部的代码也是
void IntegerLinkedList::addFirst(int x){
IntegerNode* n = new IntegerNode(x);
if (head == nullptr && tail == nullptr) {
head = n;
tail = n;
} else {
head->setPrevious(n);
n->setNext(head);
head = n;
}
}
头部在标题中定义为
IntegerNode* head;
答案 0 :(得分:1)
我对是否删除指针本身感到困惑,所以 指针不能再次指向或删除指针所在的位置 指示。
删除指针指向的内容。指针必须指向使用动态范围分配的对象(new
关键字)。
我只是删除它的所有指针。那会删除像这样的对象吗? 它会在Java?
当然不是。
或者我必须手动删除它,我该怎么做?我 记忆漏水???
你必须使用delete
关键字手动删除它,是的,除非你这样做,否则你会泄漏内存。
人们常说,如果你已经了解Java,那么从头开始学习C ++比学习C ++更容易。 C ++对象的工作方式与它们在Java中的工作方式完全不同。
并且不仅仅是以不同的方式,而是以完全没有Java相同的方式。例如,在C ++中没有自动作用域中实例化的对象的Java等价物。
在stackoverflow.com上的简短回答中无法完整地解释各种范围的C ++类实例。你需要一本关于C ++的好书,然后开始阅读它。
忘记Java中关于类的所有知识。 C ++类不能那样工作。您继续尝试使用Java进行类比的时间越长,您学习如何正确使用C ++类的时间就越长。
是的,使用智能指针可以帮助解决一些痛苦,这将解决一些痛点。但是理解智能指针本身也需要完全理解C ++的类模型。智能指针并不能解决所有问题,了解C ++类如何工作非常重要,以便了解智能指针解决的问题以及它们无法解决的问题。
答案 1 :(得分:1)
Java有一个垃圾收集器,基本上可以执行智能指针。也就是说,当对象的最后一次引用超出范围时,清理内存。
delete
关键字释放指针指向的位置的内存。它实际上并没有对指针变量本身做任何事情(它只是一个地址)。
更正代码的方法是:
else if (head == tail) { // suppose head = 0xAD4C0080
int ret = head->getData();
delete tail; // cleans memory at 0xAD4C0080, head and tail are still 0xAD4C0080
head = nullptr; // now head = 0
tail = nullptr; // now tail = 0
return ret;
} else {
IntegerNode* newHead = head->getNext();
head->setNext(nullptr);
newHead->setPrevious(nullptr);
int ret = head->getData(); // obtain data while head still exists
delete head; // get rid of head
head = newHead; // remove stray reference to deleted memory
return ret;
}
如果在这些示例中调用0xAD4C0080
后尝试使用值delete
,则会出现分段错误。
至于智能指针(引自评论):
是智能指针,但是它们会删除它所指向的内容还是仅仅是它们自己
智能指针会在它们自身被解构时删除它们指向的内容(通常是超出范围)。即。
void func() {
std::unique_ptr<int> pInt(new int);
} // pInt falls out of scope, std::unique_ptr<int>::~std::unique_ptr<int>() called
答案 2 :(得分:1)
如果您使用new
关键字,则始终需要使用delete
。使用new
分配的内存不受管理。
目前,您的程序正在使用pollFirst
方法泄漏内存,因为在重新分配它们之前,您没有释放head
和tail
指向的内存。您可以在重新分配之前致电delete head
和delete tail
来执行此操作。
如果要自动管理指针所指向的内存,应该考虑使用其中一种智能指针类型,例如unique_ptr
。
答案 3 :(得分:1)
我记忆力泄漏了吗?
是的,如果您new
某事,您必须delete
某个地方。分配指向nullptr
的指针不会影响分配的数据。
但是我对是否删除指针本身感到困惑,因此指针不能再次指向,或者它是否删除了指针指向的位置。
delete
关键字将删除您发送给它的地址的内容。它不会删除命名变量,因为堆栈中的变量在范围的末尾被破坏。手动删除具有自动存储功能的内容导致undefined behaviour
。
我发现你对std::unique_ptr
感到困惑不,他们并没有删除自己。像任何其他变量一样,它们的析构函数被调用,变量被破坏。关于std::unique_ptr
的事情是,在他们的析构函数中,他们删除了他们指向的数据,你必须自己删除它。你应该读一下RAII idom。
关于您的代码,特别是以下几行:
head = nullptr;
tail = nullptr;
delete head;
delete tail;
这不会做任何事情。您没有删除任何数据,因为head
和tail
指向任何内容。由于delete
关键字删除了指向的数据指针,因此不会删除任何内容。
但是,请将此示例与std::unique_ptr
:
{
std::unique_ptr<int> myPtr;
myPtr = std::make_unique<int>(); // or you can use `new int;`
myPtr = nullptr; // The old int you allocated with `std::make_unique` is deleted.
myPtr = std::make_unique<int>(); // assign a newly allocated int
}
// Here, myPtr will free his data as it leaves the scope.
答案 4 :(得分:1)
这取决于头部和尾部的类型。在C ++中,有运算符(例如,operator =),并且存在析构函数。这可能会导致某些有趣的后果。举个例子:
#include <memory>
int main() {
// allocate memory
int* ptr = new int;
// store in smart pointer
std::unique_ptr<int> smart_ptr(ptr);
// create another wrapped pointer
std::unique_ptr<int> smart_ptr2(new int);
// throw away location of allocated memory
ptr = nullptr;
// free memory by assigning to smart pointer
smart_ptr = nullptr;
// we can call delete safely here because ptr is null
delete ptr;
// data pointed to by smart_ptr2 will
// be deleted at end of scope
return 0;
}
此外,还有两个用于分配内存的运算符,operator new和operator new [],它们必须分别使用delete和delete []自由运行。
对这些概念的更详细解释可能超出了本网站的范围。
答案 5 :(得分:0)
关于C ++,你应该了解一些事情。
注意:如果您的类中有数据成员是指针,建议您编写自己的DTOR。