在linked list part2中, 我们定义了一个node class 如下:
有了这个node class之后, 我们可以利用这个class宣告很多的node class 的object:
然而虽然我们可以宣告很多的Contact类型的对象, 但是我们并没有将他们linke 起来组成一个linked list.。
为了实现这样的一个linked list, 我们需要宣告一个List class, 该class 具有一个指向节点类型Contact的对象的head指针变量。 最开始, 我们的head可能设置0, 也就是说我们的linked list 是empty。 一个linked list 可能有很多的operations, 例如判断其是否为空链表, 删除链表的某一个节点, 创建新的某个节点, 或者遍历链表等等。. 为了简便起见, 我们忽略其他的operations(亦methods, 也被称为成员函数)。
链表的节点添加可以从链表头向后添加(forward), 也可由从链表尾部(backWard)从后向前创建。
在这里我们介绍building linked list backward。
下面实现:
创建NewLinkedList工程中:
(1)Contact.h
/*
* Contact.h
*
* Created on: Jul 6, 2014
* Author: ***
*
*
*/
#ifndef CONTACT_H
#define CONTACT_H
#include <iostream>
#include <string>
class Contact {
friend std::ostream& operator<<(std::ostream& os, const Contact& c);
friend class ContactList;
public: //public area
Contact(std::string n = "none"); // constructor with default parameter
private: //private area
//you can add information like email address, phone number etc.
std::string name;
Contact* next;//linked pointer so it can be linked to the next node in the linked list
};
#endif // end of CONTACT_H
注意上面, 我们宣告了class ContactList 为类别Contact的友元类别。 也就说, ContactList的所有的成员函数就是类别Contact的友元函数。
所有所有ContactList 的成员函数都可以直接存取Contact的私有成员变量。
(2)Contact.cpp
/*
* Contact.cpp, implementation file of Contact.h
*
* Created on: Jul 6, 2014
* Author: ***
*
*
*/
#include "Contact.h"
using namespace std;
Contact::Contact(string n):name(n), next(NULL) {
}
// overloading insertion operator
//return ostream reference so that we can chaining "<<"
//the argument is a constant reference of type Contact
ostream& operator<<(ostream& os, const Contact& c) {
return os << "Name: " << c.name;
}
(3)类别ContactList的头文件:
/*
*ContactList.h
*
* created on Jul 6, 2014
* Author: ***
*
*
*/
#ifndef CONTACT_LIST_H
#define CONTACT_LIST_H
#include "Contact.h" // the first thing to do is to include the node header file
class ContactList {
public:
ContactList(); // prototype for constructor
void AddToHead(const std::string&);//reference, 避免复制, 更快, const, 所以不让修改
private:
Contact* head;
int length;
};
#endif /*end of CONTACT_LIST_H*/
(3)ContactList.cpp
// an implementation of ContactList.h
#include "ContactList.h"
using namespace std;
ContactList::ContactList():head(0), length(0) {
}
void ContactList::AddToHead(const string& name) {
Contact* newOne = new Contact(name);
if(head == 0) {
head = newOne;
}
else {
newOne -> next = head;
head = newOne;
}
length++;
}
在这里, 需要注意的是我们采用了动态内存分配的方法去创建从后向前我我们的linked list 添加新的节点。
即使函数调用结束, 由于是动态分配的内存, 所以不会dellocate。 但是调用函数结束后, 我们创建的节点的位置存储在newOne中, 而这个指针在函数内部声明的,所以位于stact中。 会随着函数调用的结束而被释放掉。 每次调用时 , 为这个指针重新分配内存。 也就是说创建的linked list 会保持新的程度, 实现我们的目的。
添加节点的时候。 else 里面的两个语句的顺序很重要。 不能改变顺序。 下面以几幅图说明。
最开始, 我们的指针head 指向null, 此时是空链表:
后来, 我们调用函数AddToHead("Bob"), 执行到new Contact(name)时, 如下情况:
执行语句(head == 0): head = newOne;
表达如下图:
当函数调用结束的时候, newOne由于在stack中, 所以内存会释放掉, 最终如下图:
当再次, 当我们再次调用函数AddToHead("Sally"), 执行到new Contact(name)时候, 情况如下:
由于此时head !=0, 所以会选择执行:
newOne -> next = head; head = newOne; 具体如下(两个语句先后对应下面两幅图):
当函数调用结束后, newOne 被释放掉:
注意上面的else内部的两个语句的先后顺序很重要, 要调换顺序, 会导致后面的节点丢失, 造成许多内存的浪费, 是错误的。
下面编写一个用于测试的application 文件:
//NewContactListApp
#include "ContactList.h"
using namespace std;
int main() {
ContactList* cl1 = new ContactList;
string name;
while(true) {
cout << "Enter the name of the contact, or q to quit:";
cin >> name;
if(name == "q")
break;
cl1->AddToHead(name);
}
return 0;
}
debug 查看内存个变量的变化情况。
NOTE:
CodeBlocks,cannot open output file permission denied的解决办法
在用CodeBlocks环境,mingw32编译器时经常遇到这个问题,一直的原因有两个:1.有正在run的exe文件。只要把它终结就好。2.目录名字中有空格或汉字。只要改成全英文就行了。
在这里, 我的exe被360 后的住了, 换个文件位置, 重新编译就好, 虽然运行完程序后, 360仍然会将其当做木马hold 住。 在google搜索问题根源, 得到如下答案:
If you think the executable is locked by a process, try Process Explorer from SysInternals. In the File/handle, enter Fibonacci.exe and you should see who holds the file.
If it is not enough, you can use Process Monitor (from SysInternals, again) to follow the activity of all processes on your system on Fibonacci.exe. With a little bit of analysis (call stacks), you'll may find out why the access to the file is denied and what make it disappear.