通过getter访问的c++类成员会产生垃圾,直接访问可以,但std::cout会干扰
c++ class member accessed via getter yields garbage, direct access ok but std::cout interferes?
我是c++的新手,并试图通过实现LinkedList来熟悉这种语言。
class ListElement {
public:
int val;
ListElement *next;
ListElement(int v, ListElement *n) {val = v; next = n;};
};
ListElement
包含一个int值val
、一个指向下一个列表元素的指针(如果没有下一个元素,则为nullptr
)和一个构造函数。
class MyLinkedList {
public:
ListElement *head;
MyLinkedList() {head = nullptr;};
ListElement* getHead(void){
return head;
};
void append(int i) {
head = &ListElement(i, head);
};
};
MyLinkedList
包含一个指向名为head
的列表的第一个元素的指针,以及一些处理该列表的方法。在这些方法中遇到一些错误,我试图找出它们的原因。(我知道公共类成员的getter根本没有意义,最初head
是私有的。)在这样做的时候,我观察到了以下我无法解释的行为:
int main() {
MyLinkedList l;
l.append(1);
int x = l.head->val;
cout << "head: " << x << "n";
int y = l.getHead()->val;
cout << "getHead(): " << y << "n";
int z = l.head->val;
cout << "head: " << z << "n";
cin.get();
return 0;
}
运行此代码(添加#include <iostream>
和using namespace std;
作为工作示例)将打印
head: 1
getHead(): 18085840
head: -858993460
因此,head
的第一次直接访问正如预期的那样工作,生成1
作为第一个列表元素的值,但使用getter返回垃圾。如果再次直接访问head
,它也会产生垃圾,这让我觉得"嗯,似乎使用getHead()以某种方式混淆了ListMember对象",只是为了发现
int x = l.head->val;
cout << "head: " << x << "n";
int z = l.head->val;
cout << "head: " << z << "n";
打印
head: 1
head: -858993460
甚至不接触吸气剂。那么,仅仅以任何方式访问l.head
就足以混淆它吗?
否,作为
int x = l.head->val;
int z = l.head->val;
cout << "head: " << x << "n";
cout << "head: " << z << "n";
返回(按预期)head: 1
两次。那么在更改对象或它们的指针之间使用cout
呢?getHead()
有什么问题,因为它所做的只是return head;
?
所以我在这里很迷茫,找不到任何直接相关的问题。(这个问题的标题很有希望,但不使用指针)。我是不是完全没有以正确的方式使用指针?还是在幕后自动删除对象?或者这就是magiC++的工作原理?
在中
void append(int i) {
head = &ListElement(i, head);
};
ListElement(i, head)
创建一个临时的、无名称的ListElement
,并将指向它的指针分配给head
。然后,因为ListElement
本身没有分配给任何东西,所以ListElement
超出了作用域并被销毁。这会使头指向无效内存。
磁头可以写为使用动态存储器来延长ListElement
的寿命
void append(int i) {
head = new ListElement(i, head);
};
但现在必须有人承担起确保CCD_ 23在不再需要时被删除的责任。
例如:
void remove(int i) {
// find list element i and previous element. Special handling required for first element
prev.next = element.next;
delete element;
};
仔细使用std::unique_ptr和std::move可以实现内存管理的自动化,并消除对delete
的需求。
在C++中,您必须管理自己的内存。声明
ListElement(i, head);
创建本地作用域为MyLinkedList::append()的ListElement实例。因此,一旦该函数退出,变量就不再存在,指针现在指向无效内存。
你的第一份书面陈述给你一个看似正确的答案的原因有点转移注意力。在所有情况下,您都在访问具有未定义行为的空闲内存。在第一种情况下,内存恰好具有您之前设置的值。
你必须在append中分配你自己的内存,并在完成后清理它。一旦你掌握了"new",一定要查找如何遍历数据结构并删除每个元素。对于链接列出的实现,这应该是相当琐碎的。
更改
void append(int i) {
head = &ListElement(i, head);
};
至
void append(int i) {
head = new ListElement(i, head);
};
第一个,如果它进行编译,就是获取一个临时堆栈分配对象的地址。因此head
在销毁后会"指向垃圾"。
- 我想访问std::unique_ptr中的一个特定元素
- 通过unique_ptr访问std::数组
- 访问 std:vector 的类成员 std:vector 在一个类中与另一个 std:vector
- 使用 at() 访问 std::map 元素是否比运算符 [] 慢?
- 通过作为指向 C++ 函数的指针传递来访问 std::array 元素的正确方法是什么?
- 阻止直接访问 std::map 键
- 使用 std::get 访问 std::variant<index>
- 通过引用传递时访问std::vector的元素
- 如何访问std::shared_ptr方法
- SFML访问std::vector内的数组
- 无法访问 std::p air 的成员秒
- 访问"std::vector"的保留但未调整大小的内存作为原始内存是否安全?
- 如何访问"std::variant"的任何子级的"多态"基类?
- 访问 std::multimap 值的最佳方式?
- 如何在C++中从模板化类访问 std::vector 数据
- 在VS2015中访问std::any
- 在 c++ 中访问 std::map 的多个线程
- 在 Valgrind 输出中仍然可以访问 std 线程向量的块
- 用指针访问std ::字符串中的元素
- 在 C++ 中访问 std::array<std::array> 元素