C++编程有关问题-注意指针参数的传递

C++编程问题--注意指针参数的传递
     构建一棵二叉树,并按照后序顺序来遍历它。第一次写的代码如下:
#include <iostream>

using namespace std;

class Element
{
public:
	Element* left;
	Element* right;
	char key;
	Element();
	Element(char k);
};
Element::Element()
{
	left = NULL;
	right = NULL;
	key = 0;
}
Element::Element(char k)
{
	left = NULL;
	right = NULL;
	key = k;
}

class BinaryTree
{
public:
	Element* root;
	BinaryTree();
	void createTree(Element* e);
	void postTravel(Element* e);
	void destroyTree();
};
BinaryTree::BinaryTree()
{
	root = NULL;
	cout<<"please enter the tree element by preorder:(use '#' as empty node)"<<endl;
	createTree(root);
}
void BinaryTree::createTree(Element* e)
{
        //create root node
        e = new Element();
        cin>>e->key;
        if(e->key=='#')
        {
                return ;
        }
        else
        {
                //create left child tree
                createTree( e->left );
                //create right child tree
                createTree( e->right );
        }
}
void BinaryTree::postTravel(Element* e)
{
	if(e->key=='#')
	{
		cout<<"#"<<endl;
		return ;
	}
	else
	{
		postTravel(e->left);
		postTravel(e->right);
		cout<<e->key<<endl;
	}
}

int main(void)
{
	BinaryTree tree;
	tree.postTravel(tree.root);
	return 0;
}

     想创建的树如下所示,
                                                           A
                                                        /     \
                                                       B       C
                                                     /   \    /  \
                                                    D    #    #   E
                                                   / \           / \
                                                  F   #         #   #
                                                 / \
                                                #   #
      

     #号来表示空的结点,按照先序遍历,这棵树的顺序如下:

ABDF####C#E##

     编译程序,运行,会提示按照先序遍历输入一棵树的结点,用“#”来表示空结点。输入上面的ABDF####C#E##,运行结果如下:
please enter the tree element by preorder:(use '#' as empty node)
ABDF####C#E##
Segmentation fault

发生了段错误。

     经过追查,发现是建树的时候发生的错误。在声明一个树的对象的时候,会调用默认的构造方法,而在构造方法中调用了函数createTree,该函数的参数是Element* e。在递归建树的过程中,第一次传递给createTree的参数是root,root的值是NULL。因此编译器将root的值NULL,复制了一份,保存在临时变量中,当使用new Element来分配一个新的对象的时候,并没有把这个新对象的地址保存在root的地址空间中,而是保存在了临时的变量中,所以这就是由于值传递造成的错误。在很多时候,需要特别小心在参数中带有指针的函数,这些函数往往是发生错误的根源。

     将该程序进行修改,就可以得到正确的结果:

#include <iostream>

using namespace std;

class Element
{
public:
	Element* left;
	Element* right;
	char key;
	Element();
	Element(char k);
};
Element::Element()
{
	left = NULL;
	right = NULL;
	key = 0;
}
Element::Element(char k)
{
	left = NULL;
	right = NULL;
	key = k;
}

class BinaryTree
{
public:
	Element* root;
	BinaryTree();
	void createTree(Element** e);
	void postTravel(Element* e);
	void destroyTree();
};
BinaryTree::BinaryTree()
{
	root = NULL;
	cout<<"please enter the tree element by preorder:(use '#' as empty node)"<<endl;
	createTree(&root);
}
void BinaryTree::createTree(Element** e)
{
	//create root node
	*e = new Element();
	cin>>(*e)->key;
	if((*e)->key=='#')
	{
		return ;
	}
	else
	{
		//create left child tree
		createTree( &((*e)->left) );
		//create right child tree
		createTree( &((*e)->right) );
	}
}
void BinaryTree::postTravel(Element* e)
{
	if(e->key=='#')
	{
		cout<<"#"<<endl;
		return ;
	}
	else
	{
		postTravel(e->left);
		postTravel(e->right);
		cout<<e->key<<endl;
	}
}

int main(void)
{
	BinaryTree tree;
	tree.postTravel(tree.root);
	return 0;
}

     运行的结果如下:
please enter the tree element by preorder:(use '#' as empty node)
ABDF####C#E##
#
#
F
#
D
#
B
#
#
#
E
C
A