我目前正在处理使用C ++的数据结构问题。 我将检查单链表中的节点是否按升序排序。这里有我的代码的一些细节
Node.cpp
class Node
{
public:
double data;
Node* next;
};
对于出现问题的部分,
double preValue = sLL.head->data;
Node *curNode = sLL.head->next;
do
{
if (preValue > (preValue = curNode->data)) // Problem occur in this line
return false;
}while (curNode = curNode->next);
作为'>'的评估顺序运算符正在评估左侧表达式,然后是右侧表达式
和
赋值运算符将返回左值的引用。
因此,preValue > (preValue = curNode->data)
应比较最后一个节点和当前节点,并在完成比较后分配下一个节点的数据。因此,我认为我的实施应该是有效的。
但是,if(preValue > (preValue = curNode->data))
的结果超出了我的预期,当比较preValue
大于新preValue
时,它会一直返回false。
我试图打印出if语句的返回值,只要左表达式大于或小于右表达式,它总是返回0。 我不明白为什么会这样。谁能告诉我我犯了什么错误?
P.S。该程序可以正常使用以下实现
double preValue = list.head->data;
Node *curNode = list.head->next;
do
{
if (preValue > curNode->data) // Check ascending order
return false;
preValue = curNode->data;
}while (curNode = curNode->next);
答案 0 :(得分:3)
这一行是未定义的行为:
if (preValue > (preValue = curNode->data)) // Problem occur in this line
因为您要分配给变量(preValue
)并从同一个变量读取,而读取不用于确定写入的值。
来自C ++03§5/ 4 [expr]
:
[...]之间的比较 和下一个序列点标量对象的评估值最多只能修改一次 一个表达。此外,只能访问先前值以确定要存储的值。 对于完整的子表达式的每个允许排序,应满足本段的要求 表达;否则行为未定义。
序列点出现在完整表达式(即以分号结尾的表达式或语句)之后,以及&&
,||
,{{的第一个操作数之后。 1}}和?:
运算符。所有其他运算符(包括,
运算符) not 在其参数的求值之间具有序列点。序列点也出现在与此问题无关的其他几个地方。
正如你所说,修复只是将它拆开,以便在比较的单独声明中进行赋值。
当我使用带有>
编译器标志的GCC编译此代码时,我收到此警告:
-Wall
我强烈建议您始终使用warning: operation on ‘preValue’ may be undefined [-Wsequence-point]
和-Wall
进行编译,以便编译器立即标记这些错误,您可以更正它们。
答案 1 :(得分:0)
这一行
if (preValue > (preValue = curNode->data))
是未定义的行为。请参阅sequence points的概念。表达式只能在两个序列点和'>'之间修改其对象一次不是序列点。