我定义了两个类:
template<class Datatype>
class Node
{
public:
Node()
{
next = NULL;
prev = NULL;
}
Node* getNext()
{
return next;
}
Node* getPrev()
{
return prev;
}
Datatype* getData()
{
return &data;
}
void changeNext()
{
next = NULL;
}
void changeNext(Node& nextNode)
{
next = &nextNode;
}
void changePrev()
{
prev = NULL;
}
void changePrev(Node& prevNode)
{
prev = &prevNode;
}
Node* addNext(Node &);
Node* addPrev(Node &);
void nodeDel();
void addData(Datatype &);
private:
Node* next;
Node* prev;
Datatype data;
};
template<class Datatype>
class Stack
{
public:
Stack() : node()
{
;
}
int push(Datatype &);
Datatype pop();
Datatype* peek();
private:
Node<Datatype> node;
};
我试图做一些调试。我使用函数调用将数据包推送到此堆栈中:
template <class Datatype>
int Stack<Datatype>::push(Datatype &new_data)
{
Node<Datatype> *pt_node = new Node<Datatype>;
if (pt_node == NULL)
return -1;
Datatype *pt_data;
pt_data = (this -> node).getData();
pt_node -> addData(*pt_data);
(this -> node).addData(new_data);
pt_node -> addNext(this -> node);
cout << ((node.getNext())) << endl;
return 0;
}
我打印出了节点的下一个指针。它应该是NULL
的,因为它是堆栈中唯一的数据包,结果证明了这一点。调用此函数时的输出为 0。但是,我稍微更改了推送函数的cout
指令:
cout << ((node.getNext()) -> getData()) << endl;
我尝试打印出下一个节点的数据。显然什么都不应该存在,因为该节点不存在,我已经证明node.getNext()
返回0
。奇怪的是分段错误没有发生在这里,它确实有一个输出0x8。我不知道这是怎么发生的。
getData
返回指向成员的指针;因此它不需要取消引用this
,只需为其添加偏移量即可。这就是为什么即使this
为空也不会得到分段错误的原因。
当然,这仍然是未定义的行为。
取消引用 NULL 指针是未定义的行为,这实际上意味着任何事情都可能发生,它不能保证崩溃(尽管操作系统可能会为了自身安全而使您的应用程序崩溃)这是高度依赖于实现的,并且此类代码不应存在于您的应用程序中。
引用标准
注意:特别是,空引用不能存在于定义良好的 程序,因为创建此类引用的唯一方法是 将其绑定到通过取消引用空指针获得的"对象", 这会导致未定义的行为。如 9.6 中所述,参考 不能直接绑定到位域。——尾注