How to construct a universal object linked list in CC ++

xiaoxiao2021-03-06  45

How to construct universal object linked list in C / C is a good implementation of this

T. W. Burgerthomas Wolfgang Burger Consulting's boss in September 2000

Content: Simplified Problem C Code Solutions C Solution Summary Reference Resources Author

Have you done such a project, which requires you to save a number of different objects in memory? For some cases, the binary tree is the best choice, but in general, a simpler chain list is an obvious choice.

A simplified problem example chain table is difficult to copy the chain list handler to handle different objects, even if the logic is identical. E.g:

Two structures Similar Linches

Struct Struct_Object_a

{

Int a;

INT B;

Struct_Object_a * next;

} Object_a;

Typedef struct struct_object_b

{

Int a;

INT B;

INT C;

Struct_Object_b * next;

} Object_b;

The two structures defined above are only a small difference. Between Object_b and Object_a is only a integer variable. However, in the compiler, they are still very different. You must copy, delete, and search the linked list for each object stored in the linked list. In order to solve this problem, a joint or structure with all three variables can be used, where integer C is not used in all cases. This may become very complicated and will form a bad programming style.

C Code Solution: One of the better solutions for virtual chains is a virtual chain table. The virtual linked list is a list containing only the list pointer. Objects are stored behind the chain table structure. This is true, first assigning memory for the chain table node, then assigns memory to the object, and then assign the memory to the chain table node pointer, as shown below:

An implementation of virtual link structure

Typedef struct liststruct

{

Liststruct * next;

} List, * plist;

PLIST head = null;

PList Addtolist (PLIST Head, Void * Data, Size_t DataSize)

{

Plist newlist = null;

Void * p;

// Assign node memory and data memory

NEWLIST = (PLIST) Malloc (Datasize SizeOf (List));

/ / Specify a pointer for this data buffer

P = (void *) (newlist 1);

// copy data

Memcpy (P, Data, DataSize);

// Specify this node to the header of the list

IF (HEAD)

{

Newlist-> next = head;

}

Else

Newlist-> next = null;

HEAD = newlist;

Return head;

}

The chain table node is now based on the basics of a copy of the data value. This version can handle scalar values ​​well, but cannot handle objects with an element with Malloc or NEW allocation. To handle these objects, the List structure needs to include a general release function pointer, which can be used to release the node from the linked list to release the memory (or turn the file, or call the shutdown method) from the linked list.

A linked list with release functions

Typedef void (* listnodedestructor) (void *);

Typedef struct liststruct

{

ListNodedestructor DestructFunc;

Liststruct * next;

} List, * plist; plist addtolist (PLIST head, Void * Data, Size_t DataSize,

ListNodedestructor Destructor)

{

Plist newlist = null;

Void * p;

// Assign node memory and data memory

NEWLIST = (PLIST) Malloc (Datasize SizeOf (List));

/ / Specify a pointer for this data buffer

P = (void *) (newlist 1);

// copy data

Memcpy (P, Data, DataSize);

Newlist-> deStructFunc = Destructor;

// Specify this node to the header of the list

IF (HEAD)

{

Newlist-> next = head;

}

Else

Newlist-> next = null;

HEAD = newlist;

Return head;

}

Void deletelist (PLIST HEAD)

{

PLIST NEXT;

While (Head)

{

NEXT = head-> next;

Head-> deStructFunc ((void *) head);

Free (Head);

HEAD = NEXT;

}

}

Typedef struct listdatatruct

{

LPSTR P;

} List_data, * plist_data;

Void ListDataDestructor (void * p)

{

/ / Type to the node pointer

PLIST PL = (PLIST) P;

// Type conversion for the data pointer

PLIST_DATA PLD = (PLIST_DATA) (PL 1);

Delete PLD-> P;

}

PLIST head = null;

void testlist ()

{

PLIST_DATA D = New List_Data;

D-> p = new char [24];

STRCPY (D-> P, "Hello");

Head = addtolist (head, (void *) d, sizeof (plist_data),

ListDataDestructor;

/ / The object has been copied, and now deletes the original object.

Delete D;

D = new list_data;

D-> p = new char [24];

STRCPY (D-> P, "world");

Head = addtolist (head, (void *) d, sizeof (plist_data),

ListDataDestructor;

Delete D;

// Release the list

Deletelist (HEAD);

}

The same pointer containing the same release function in each chain table node seems to be a waste of memory space. This is true, but only the linked list always contains the same object to belong to this. Writing a list in this way allows you to place any object anywhere in the linked list. Most linked list functions require objects that are always the same or class. The virtual chain table does not require this. It is only a method of separating objects to each other. To achieve this, you can detect the values ​​of the release function pointer, or you can add a type value before all of which are used in the list and detect it. Of course, if you want to write a chain as a C class, you can only turn once for the settings and storage of pointers to the release function.

C solution: Class link list This solution defines a CLIST class as a class exported from the List structure, which handles a single storage type by storing a single value of the release function. Note that the added getCurrentData () function, the function completes the mathematical conversion from the chain table node pointer to the data offset pointer. A virtual chain table object

// Define the release function pointer

Typedef void (* listnodedestructor) (void *);

// Dissolve Lin table

Typedef struct ndliststruct

{

NDLISTSTRUCT * NEXT;

} Nd_list, * pnd_list;

// Define the chain class for processing a data type

Class Clist: Public ND_LIST

{

PUBLIC:

Clist (ListNodedestructor);

~ Clist ();

Pnd_list addtolist (void * data, size_t datasize);

Void * getcurrentdata ();

Void deletelist (PND_LIST HEAD);

Private:

PND_LIST M_HEADOFLIST;

PND_LIST M_CURRENTNODE;

ListNodeDestructor M_DestructFunc;

}

// Construct this linked object with the correct start value

CList :: Clist (ListNodedestructor Destructor)

: m_headoflist (null), M_CurrentNode (NULL)

{

m_destructfunc = destructor;

}

// Remove the linked list after the object

Clist :: ~ clist ()

{

Deletelist (m_headoflist);

}

/ / Add a new node to the list

PND_LIST CLIST :: Addtolist (void * data, size_t datasize)

{

PND_LIST NEWLIST = NULL;

Void * p;

// Assign node memory and data memory

NEWLIST = (PND_LIST) Malloc (DataSize SizeOf (ND_LIST));

/ / Specify a pointer for this data buffer

P = (void *) (newlist 1);

// copy data

Memcpy (P, Data, DataSize);

// Specify this node to the header of the list

IF (M_Headoflist)

{

Newlist-> next = m_headoflist;

}

Else

Newlist-> next = null;

M_Headoflist = newlist;

Return M_Headoflist;

}

// Return the current node data as a Void type so that the call function can convert it to any type

void * clist :: getcurrentdata ()

{

Return (void *) (M_CurrentNode 1);

}

// Delete the assigned list

Void Clist :: deletelist (pnd_list head)

{

PND_LIST NEXT;

While (Head)

{

NEXT = head-> next;

m_destructfunc ((void *) head);

Free (Head);

HEAD = NEXT;

}

}

// Create a structure to create and store it in the list

Typedef struct listdatatruct

{

LPSTR P;

} List_data, * pnd_list_data;

/ / Define Standard Release Function

Void ClassListDataDestructor (void * p) {

/ / Type to the node pointer

PND_LIST PL = (PND_LIST) P;

// Type conversion for the data pointer

PND_LIST_DATA PLD = (PND_LIST_DATA) (PL 1);

Delete PLD-> P;

}

// Test the code above

void myclistclasstest ()

{

// Create a list class

CLIST * PA_LIST_OF_DATA = New Clist (ClassListDataDestructor);

// Create a data object

PND_LIST_DATA D = New List_Data;

D-> p = new char [24];

STRCPY (D-> P, "Hello");

// Create a partial pointer to the top of the list

PND_LIST HEAD = NULL;

/ / Add some data to the list

HEAD = pa_list_of_data-> addtolist (void *) D,

SIZEOF (PND_LIST_DATA);

/ / The object has been copied, and now deletes the original object.

Delete D;

// Confirm that it has been stored

Char * p = ((pnd_list_data) pa_list_of_data-> getCurrentData ()) -> P;

D = new list_data;

D-> p = new char [24];

STRCPY (D-> P, "world");

Head = pa_list_of_data-> addtolist (void *) D, SIZEOF (PND_LIST_DATA));

/ / The object has been copied, and now deletes the original object.

Delete D;

// Confirm that it has been stored

P = ((pnd_list_data) pa_list_of_data-> getCurrentData ()) -> P;

/ / Delete the list class, the destructor will delete the list

DELETE PA_LIST_OF_DATA;

}

Summary From the previous discussion, it seems that only a simple list is to do a lot of work, but this must only be done. It is easy to expand this code into a C class that handles sort, search, and various other tasks, and this class can process any data objects or classes (in one project, which process about twenty different objects). You will never have to reply this code.

Reference resource

The Linux C Programming Lists is designed to help people use the C language Linux programming, including many links to mailing lists, common questions, tutorials, and other content links. Microsoft Foundation Class provides similar features in its CLIST class. The CLIST in the MFC and other types of requirements or classes can only be a type. The programmer does not have control over the code, which is different from zero.

转载请注明原文地址:https://www.9cbs.com/read-79142.html

New Post(0)