- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个节点列表,每个节点包含一个指向学生变量(这是一个类)的指针,以及一个指向下一个节点的指针。这是我的 insertAtTail 代码。
void studentRoll::insertAtTail(const Student &s) {
if (head == NULL) {
this->head = new Node;
this->head->next = NULL;
this->head->s = new Student(s);
this->tail = head;
}
else {
this->tail->next = new Node;
this->tail = this->tail->next;
this->tail->next = NULL;
this->tail->s = new Student(s);
}
}
我用valgrind调试,得到:
==11106== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==11106== at 0x4C2D1CA: operator new(unsigned long)
(vg_replace_malloc.c:334)
==11106== by 0x402BE7: StudentRoll::insertAtTail(Student const&)
(studentRoll.cpp:15)
==11106== by 0x401CF1: main (testStudentRoll01.cpp:19)
==11106==
==11106== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==11106== at 0x4C2D1CA: operator new(unsigned long)
(vg_replace_malloc.c:334)
==11106== by 0x402C5B: StudentRoll::insertAtTail(Student const&)
(studentRoll.cpp:22)
==11106== by 0x401E2C: main (testStudentRoll01.cpp:27)
==11106==
有人可以帮我吗?我认为存在一些问题:
this->head->s = new Student(s);
和
this->tail->s = new Student(s);
但我不能删除它们,因为我需要这些“学生”。并且有指向“学生”的指针。
谢谢!!
更新:这是我的析构函数
StudentRoll::~StudentRoll() {
Node *iter = head;
while (iter) {
Node *next = iter->next;
iter->s->~Student();
delete iter;
iter = next;
}
head = tail = NULL;
}
最佳答案
Can someone help me with it? I think there are some problems about:
this->head->s = new Student(s);
and
this->tail->s = new Student(s);
But I cannot delete them because I need these "Students." And there are pointers point to "Students."
这个问题可能表明您应该重新设计您的程序。在 C++ 中,您应该表达所有权语义并明确哪些对象拥有哪些资源并负责它们的清理。 C++ 中的所有权语义通过各种指针类型表示:
如果某个单个对象拥有一些堆内存,而不是直接使用原始指针和new
和delete
,请使用std::unique_ptr
. std::unique_ptr
更好,因为它向读者传达了您的意图并使用了 RAII以帮助防止内存泄漏。
另一方面,如果对象不拥有一 block 内存,则使用引用或原始指针代替。 (在未来,C++ 标准库可能会得到一个非拥有的智能指针。)
如果您的链表数据结构拥有学生对象,它应该是释放它们的对象。在这种情况下,使用 std::unique_ptr
:
void studentRoll::insertAtTail(const Student &s) {
if (head.get() == nullptr) {
this->head = std::make_unique<Node>();
this->head->next = nullptr;
this->head->s = std::make_unique<Student>(s);
this->tail = &*head; // Get a raw pointer
}
else {
this->tail->next = std::make_unique<Node>();
this->tail = &*this->tail->next; // Get a raw pointer
this->tail->next = nullptr;
this->tail->s = std::make_unique<Student>(s);
}
}
不使用 std::unique_ptr
,另一种选择是简单地使 Student
成为您的 Node
类型的数据成员。但是,此决定可能表明不同的意图并具有不同的含义。例如,如果您想将 Student
对象的所有权从 Node
对象转移到其他地方,您应该使用 std::unique_ptr
。如果将 Student
对象直接保留为成员,则可以通过调用 Student
的移动构造函数来实现类似的效果,但某些语义仍然不同。例如,指向 Student
的指针将失效。参见 https://stackoverflow.com/a/31724938/8887578对这两种方法进行更多比较。
如果学生对象比链表还长,那么它不应该是它们的所有者,最好使用指向此类对象的非所有者指针。在这种情况下,不要分配新的学生对象,而是从其他地方取一个指针:
void studentRoll::insertAtTail(const Student* s) {
if (head.get() == nullptr) {
this->head = std::make_unique<Node>();
this->head->next = nullptr;
this->head->s = s;
this->tail = &*head;
}
else {
this->tail->next = std::make_unique<Node>();
this->tail = &*this->tail->next;
this->tail->next = nullptr;
this->tail->s = s;
}
}
我不知道你的程序的上下文(例如,如果它是编写链表的学校练习),但在严肃的代码中,你应该使用标准库的 std::list
滚动你自己的链表。然而,在许多情况下,std::vector
(类似于动态增长的数组)比链表更合适。
此外,与其为 Node
提供一个无参数的默认构造函数,然后再分配其 s
成员,不如在其构造函数中将学生指针传递给它。
关于c++ - C++中学生指针节点列表中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50082539/
如标题所示,ans_list是一个答案列表,ans_index是一个数字(答案在词汇表中的索引,但与atm无关) 这里生成的 tree.anslist 是什么? (例如,仅针对第一个),忽略迭代。 f
我目前将用户的输入存储在逗号分隔的列表中,如下所示: Userid | Options 1 | 1,2,5 用户在一个数组形式中勾选一组选项,然后用逗号连接起来 1,2,5 然后 MySQ
我目前将用户的输入存储在逗号分隔的列表中,如下所示: Userid | Options 1 | 1,2,5 用户在一个数组形式中勾选一组选项,然后用逗号连接起来 1,2,5 然后 MySQ
我想知道如何完全展平列表和包含它们的东西。除其他外,我想出了一个解决方案,它可以将具有多个元素的东西滑倒并将它们放回原处,或者在滑倒后将具有一个元素的东西拿走。 这与 How do I “flatte
我想知道如何完全展平列表和包含它们的东西。除其他外,我想出了一个解决方案,它可以将具有多个元素的东西滑倒并将它们放回原处,或者在滑倒后将带有一个元素的东西拿走。 这与 How do I “flatte
这个问题已经有答案了: Convert nested list to 2d array (3 个回答) 已关闭 7 年前。 java中有没有快捷方式可以转换 List> 到 String[][] ?
我在排序时遇到问题 List> 。我创建了一个自定义比较器,在其中编写了对数据进行排序的代码。 public class CustomComparator implements Comparator
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: Java Generics: Cannot cast List to List? 我只是想知道为什么下面的java代
试图想出一个 LINQy 方法来做到这一点,但我什么也没想到。 我有一个对象列表<>,其中包含一个属性,该属性是逗号分隔的字母代码列表: lst[0].codes = "AA,BB,DD" lst[1
假设我有这些任务: points = [] point = (1, 2) 我怎么会这样做: points += point 它工作得很好,并且给了我点 = [1, 2]。但是,如果我这样做: poin
如何在 scala 中将 List[Task[List[Header]]] 类型转换为 Task[List[Header]]。 我有一个方法返回 Task[List[Header]] 并多次调用 do
如何在 Java 中查找二维列表的元素? 我有一个参数为 List> 的函数我想知道如何找到这个列表的行和列。 最佳答案 如果你喜欢 List> obj 然后你就可以像这样访问 obj.get(cur
分配 List到 List工作正常。 分配 List>到 List>不编译。 代码 public class Main { public static void main(String[] a
我正在用 Java 编写一个方法,该方法必须接收并迭代 Serializable 的 List。 有什么区别: public void myMethod(List list) { } 和 public
我看到很多人想用 mvvm 更新网格/列表/树的一部分,但他们不想刷新整个列表。 对于所有遇到此问题的人,我做了以下示例。 希望这对你有用。 最佳答案 这是一个简单的例子。整个代码中最重要的是: Bi
我正在为现有的 C++ 库编写包装器,该库使用列表,其中 T 是自定义结构。我被建议使用 vector 而不是列表,但我试图避免修改库。 为了更好地理解这个场景,我做了一个简单的应用程序,使用一个列表
List list List list 这两种声明有什么区别吗? 谢谢, 最佳答案 是的。 List可以包含所有派生自 Base 的不同事物的混合物. List包含同质项(从某种意义上说,它们必须全部
有人可以尽可能详细地解释以下类型之间的区别吗? List List List 让我更具体一点。我什么时候想使用 // 1 public void CanYouGiveMeAnAnswer(List l
我有一个元组列表,每个元组都是一对列表。所以我的数据看起来像: mylist = [(['foo', 'bar'], ['bar', 'bar']),(['bar', 'bar'],['bar', '
也许是一个时髦的标题,但我遇到了以下问题: 给定一个类型为 (a * b) list 的列表,我想创建一个类型为 (a * b list) list 的新列表。一个例子: 给定列表 let testL
我是一名优秀的程序员,十分优秀!