链表打印意外值
Linked list prints unexpected value
无论我检查了多少引用,我总是发现我的实现是健全的。然而,这个程序不起作用,我不知道为什么。请帮忙。非常感谢。我有这类
class intNode
{
int x;
intNode * next;
public:
intNode();
intNode(int y, intNode *p);
setNode(int y, intNode *p);
int getX();
void setX(int y);
void setNext(intNode *p);
intNode* getNext();
};
以及此类
class intList
{
private:
intNode * head;
public:
intList(); //sets head=NULL
void push( int x);
void print();
}
推送如下
void intList::push(int x)
{
intNode *newNode;
newNode->setX(x);
newNode->setNext(head);
head = newNode;
}
打印如下
void intList::print()
{
intNode *current = head;
cout << "Printing list" << endl;
while(current != NULL)
{
cout << current->getX() << "t";
current = current->getNext();
}
cout << endl;
}
但不知怎么的,主中的这段代码
intList l;
l.push(5);
l.print();
返回这个奇怪的值:6946556
让我们检查一下push
方法,看看哪里出了问题。
intNode *newNode;
现在有一个名为newNode
的变量,它是指向intNode
的指针。该指针当前未设置为任何内容(我们称之为"未初始化")。
试图访问一个未初始化的变量(例如取消引用它或调用它的方法)会导致未定义的行为,这是另一种表示"所有赌注都落空了"的方式——标准没有说明应该发生什么,所以编译器可以生成它想要的任何东西。
所以当你这样做的时候:
newNode->setX(x);
您现在正在对未初始化的指针newNode
调用一个方法。除此之外的任何事情都与我们对代码的检查几乎无关,因为编译器在优化程序时可能会无意中做一些看似"疯狂"的事情。
例如,您的程序在g++ 6.4.0
和-O0
上运行良好。它打印5。这是因为编译器没有优化任何东西,而且我们显然很幸运,newNode
"碰巧"的值实际上是一个有效的地址。
然而,当我转到-O1
时,程序实际上根本没有输出任何值。我的怀疑是,编译器发现push
在所有代码路径上都会导致UB,因此得出结论,决不能调用push
,而且根本不需要为该方法生成任何程序集(注意:我当时没有在程序集中验证这一点。)
当调用未定义的行为时,这只是会发生的疯狂事情之一——请参阅上面链接的文章了解其他一些内容。未定义的行为应永远不要发生在代码中。
现在,正确的做法是分配一个新的节点,并将指针设置为指向它
intNode *newNode = new intNode();
,那么您的代码看起来不错。不要忘记new
是一个堆分配——当不再需要时(当删除节点时),你的工作是确保它是delete
d,否则你会有没有使用的内存(内存泄漏)。
PS:如果你用-Wall
选项调用g++
,它会警告你这个错误:
test.cpp: In member function ‘void intList::push(int)’:
test.cpp:30:17: warning: ‘newNode’ is used uninitialized in this function [-Wuninitialized]
newNode->setX(x);
总是要注意编译器的警告——它们通常是有充分理由的!
在intList::push
中,它不创建新节点,而是使用不确定的指针值。
必须分配新节点:
void intList::push(int x) {
head = new intNode(x, head);
}
您可能希望在编译代码时启用警告,因为这将是编译器警告。对于g++
,请使用-Wall -Wextra -Werror
命令行选项。
Treeston很好地解释了为什么这里会出现任意wierdness,但我不喜欢他使用new
的建议。
您的intNode拥有next
指针,它是唯一的所有者,因此您应该使用std::unique_ptr
。类似地,intList拥有head
。
class intNode {
friend class intList;
int x;
std::unique_ptr<intNode> next;
public:
intNode();
intNode(int _x, std::unique_ptr<intNode> _next);
int getX();
intNode * getNext();
};
intNode::intNode() {}
intNode::intNode(int _x, std::unique_ptr<intNode> _next)
: x(_x), next(std::move(_next)) {}
class intList {
std::unique_ptr<intNode> head;
public:
void push(int x);
void print();
}
void intList::push(int x) {
head = std::make_unique(x, std::move(head));
}
void intList::print()
{
cout << "Printing list" << endl;
for(intNode * current = head.get(); current; current = current->getNext())
{
cout << current->getX() << "t";
}
cout << endl;
}
- 如何循环打印顶点结构
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 如何在c++中打印目录
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 在线编译器中的分段C++没有打印消息
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 在C++中对T*类型执行std::move的意外行为
- 声明双重给它一个值0,但打印结果意外变化
- 打印对象矢量的意外输出
- 这个std :: cout最终会打印垃圾还是意外的东西
- 链表打印意外值
- 为什么我的功能(在二进制树上)打印出意外的结果
- 带有布尔转换的变量的原始打印:意外行为
- 将time_t打印为长int而不进行强制转换会产生意外行为
- 打印函数会返回一个意外值,原因是什么
- C++线程意外地打印多次相同的行
- 打印我的Get MAC地址函数的std::字符串时出现意外输出
- 初始化数组工作得很好,但是当试图将其打印出来时,它会打印出一个额外的列和一个意外字符
- 使用cout将数组和字符打印到屏幕时出现意外结果