C common template martial arts will be the first place:
Vector v.s. list v.s. degue
Original author: beyond_ml
Ladies & Gentlem:
Hello everyone, here is the scene of the first C template martial arts meeting, this martial arts will be eastward by beyond_ml, the first nepon is beyond_ml. Because the first time the unprecedented event is held, it is inevitable that there is an omission, please also ask everyone to enlighten me. Beyond_ml is reasonable. At the same time, you will also welcome prawns to regard this martial arts as a virtual base class, constantly inherit, derived a new game.
Game start:
First introduce the contestants:
Vector: Jinshan Words Translated into: Vector, Vector, etc., the big brother in the C container template is like a strengthening queue, which is because it not only has the index of the queue, but also develops an expansion . Use especially in many classic textbooks in many classic textbooks.
Features: Store the object being included in the form of an array, supports access in the form of an index (which is very fast). However, there is also a problem, because the data storage form is fixed, if you want to be in the intermediate INSERT object, you will make you feel hard. Because he is assigning space, it is a continuous space assigned.
"Double-ended-queue" in English. Name, this is a famous two-way queue in the C ordered container. At the beginning of the design, he made special optimization for adding and deleting elements from both ends. Also supports access, also have a [] operator similar to the vector, but everyone should not mix him and vector to a pool.
Features: From essentially, he uses MAP structure and method when allocating memory. Tintered into zero, allocated many small continuous spaces, so it is very convenient to delete elements from both ends of Deque. The most important point: If you don't know if the memory is required, use Deque is definitely better than Vector, how is it well, and a certificate. In addition, inserting a sentence, I don't know if it is interested, in most cases, Deque and Vector are used interchangeably.
List: two-way linked list in the template. Designing his purpose may be to insert, delete it in the middle of the container, so there is no loss, his random access speed does not dare. And there is no [] operation. Even if you are in order from the order in the order, you don't see how much it will be fast.
Features: Random insertion, delete elements, accounts for a significant advantage at speeds. Also, because the memory allocation is discontinuous, his requirements for the insert are also very low. So when you use a big object, this is a good choice.
"Don't talk about leisure, start, start."
"咚 ..."
Fighting official start:
The first bureau: is more than one more memory management.
Method: Artificially caused storage of object data overflow, look at system consumption. System consumption here refers to: Object constructor, copy function, and sect number of call times.
The test procedure is as follows:
Noisy.h ... contains test objects, each time you call constructs, copy, and destructuring functions, you will print the corresponding prompts.
//: c04: noisy.h
// a class to track various object activity activities # ifndef noisy_h
#define noisy_h
#include
Class noisy
{
Static Long Create, Assign, Copycons, Destroy
Long id;
PUBLIC:
Noisy (): ID (Create )
{
Std :: cout << "D [" << ID << "]";
}
Noisy (const noisy & rv): id (rv.id)
{
Std :: cout << "C [" << ID << "]";
CopyCons ;
}
Noisy & Operator = (const noisy & rv)
{
Std :: cout << "(" << ID << ") = [" <<
RV.ID << "]";
ID = rv.id;
ASSIGN ;
RETURN * THIS;
}
Friend Bool
Operator <(Const Noisy & LV, Const Noisy & R)
{
Return lv.id } Friend Bool Operator == (Const noisy & lv, const noisy & rv) { Return lv.id == rv.id; } ~ Noisy () { Std :: cout << "~ [" << ID << "]"; DESTROY ; } Friend Std :: Ostream & Operator << (std :: ostream & os, const noisy&) { Return OS << n.id; } Friend class noisyreport; } Struct noisygen { Noisy operator () () {return noisy (); } // a singleton. Will Automatically Report Thae // statistics as the program terminates: Class noisyreport { Static noisyreport nr; NoisyReport () {} // private constructor PUBLIC: ~ Noisyreport () { Std :: cout << "/ N ------------------ / N" << "Noisy Creations:" << Noisy :: Create << "/ ncopy-constructions:" << Noisy :: CopyCons << "/ nassignments:" << noisy :: assign << "/ ndestructions:" << noisy :: destroy << std :: endl; } } // Because of these this file can only be used // in Simple Test Situations. Move THEM TO A // .cpp file for more complex programs: Long Noisy :: Create = 0, noisy :: assign = 0, Noisy :: CopyCons = 0, noisy :: destroy = 0; Noisyreport Noisyreport :: Nr; #endif // noisy_h ///: ~ Target: Insert a thousand noisy objects. Vector played //: c04: Vectoroverflow.cpp // shows the copy-construction and destruction // That Occurs WHEN A Vector Must Reallocate // (IT MAINTAINS a LINEAR ARRAY of Elements) #include "noisy.h" #include #include #include #include Using namespace std; Int main (int Argc, char * argv []) { INT size = 1000; IF (argc> = 2) size = atoi (Argv [1]); VECTOR Noisy n; For (int i = 0; i VN.PUSH_BACK (N); Cout << "/ n cleaning up / n"; } ///: ~ Test Results: Noisy Creations: 1 (Constructor Call) Copy-Constructions: 2023 (copy function call) Assignments: 0 (assignment) DESTRUCTIONS: 2024 (destructor call) BEYOND_ML Comments: Wow! Boss, I just insert a thousand objects, how do you suddenly call 2023 copy functions, the corresponding 2024 episodes call,, it seems that if you inserted more than his retention space, Vector The movement of moving is very big. Deque playing The code section can look at the vector because they are too like. Test Results: NoiSy Creations: 1 Copy-Constructions: 1007 Assignments: 0 DESTRUCTIONS: 1008 BEYOND_ML Comments: Well, not bad. However, the seven of that come out is not very good. List playing The code part continues to copy. Test Results: NoiSy Creations: 1 Copy-Constructions: 1000 Assignments: 0 DESTRUCTIONS: 1001 BEYOND_ML Comments: Perfect! very good! Over. The first game ends List win! The second game is more than a random access (access speed is used as a clock cycle) How does the voice just fall? How does the List have a white flag? Oh, I remembered, he does not support random access strategy. That is, there is no [] and AT () operation. Test procedure: indexingvsat.cpp Insert a thousand data, randomly accessed one million times with [] and AT (), compare clock cycles. //: c04: indexingvsat.cpp // comparing "at ()" to operator [] #include #include #include #include Using namespace std; Int main (int Argc, char * argv []) { Long count = 1000; INT SZ = 1000; IF (argc> = 2) count = ATOI (Argv [1]); IF (Argc> = 3) SZ = ATOI (Argv [2]); Vector Clock_t ticks = clock (); For (int I1 = 0; I1 For (int J = 0; j Vi [J]; COUT << "Vector [] << Clock () - Ticks << Endl; Ticks = clock (); For (int I2 = 0; i2 For (int J = 0; j vi.at (j); COUT << "Vector :: at ()" << Clock () - Ticks << Endl; DEQUE Ticks = clock (); For (int i3 = 0; i3 For (int J = 0; j Di [J]; COUT << "Deque []" << clock () - ticks << endl; Ticks = clock (); For (int i4 = 0; i4 For (int J = 0; J Di.at (j); Cout << "Deque :: at () << Clock () - Ticks << endl; // Demonstrate at () when you go out of bounds: //di.at (vi.size () 1); error here. } ///: ~ Test Results: Vector [] 360000 Vector :: at () 790000 Deque [] 1350000 Deque :: at () 1750000 Beyond_ml Comments: Sure enough, don't know, a smile. Vector wins absolutely advantage! The third game is higher than the rear insert and the speed of Iterator The insertion method mainly uses Push_Back. Then complete the operation of the data by the internal Iterator pointer. Test file: Require.h mainly includes some file operations. //:: Require.h // Test for error conditions in programs // local "Using Namespace Std" for Old Compilers #ifndef required_h #define require_h #include #include #include Inline Void Require (Bool Requirement, Const Char * MSG = "Requirement Failed") { Using namespace std; IF (! request) { FPUTS (MSG, STDERR); FPUTS ("/ n", stderr; Exit (1); } } Inline Void Requireargs (int Argc, int args, const char * msg = "must use% d arguments") { Using namespace std; IF (argc! = args 1) { FPRINTF (stderr, msg, args); FPUTS ("/ n", stderr; Exit (1); } } Inline Void Requireminargs (int Argc, int minArgs, const char * msg = "Must use at least% D arguments) { Using namespace std; IF (argc { FPrintf (stderr, msg, minargs); FPUTS ("/ n", stderr; Exit (1); } } Inline Void Assure (std :: ifstream & in, const char * filename = ") { Using namespace std; IF (! in) { FPRINTF (stderr, "could not open file% s / n", filename); Exit (1); } } Inline Void Assure (std :: OFSTREAM & IN, Const char * filename = "") { Using namespace std; IF (! in) { FPRINTF (stderr, "could not open file% s / n", filename); Exit (1); } } #ENDIF StringDeque.cpp test main program //: c04: Stringdeque.cpp // converted from stringVector.cpp #include "required" require.h " #include #include #include #include #include #include #include #include #include Using namespace std; int main (int Argc, char * argv []) { Requireargs (Argc, 1); IFStream in (Argv [1]); Assure (in, argv [1]); Vector DEQUE List String line; // Time Reading Into Vector: Clock_t ticks = clock (); While (In, Line)) vstrings.push_back (line); Ticks = clock () - ticks; Cout << "Read Into Vector:" << Ticks << Endl; // Repeat for Deque: IFStream IN2 (Argv [1]); Assure (IN2, Argv [1]); Ticks = clock (); While (getLine (in2, line)) DStrings.push_back (line); Ticks = clock () - ticks; Cout << "Read INTO Deque:" << Ticks << Endl; // repeat for list: IFStream IN3 (Argv [1]); Assure (In3, Argv [1]); Ticks = clock (); While (getLine (in3, line)) Lstrings.push_back (line); Ticks = clock () - ticks; COUT << "Read Into List: << Ticks << Endl; // compare ity OFSTREAM TMP1 ("TMP1.TMP"), TMP2 ("TMP2.TMP"), TMP3 ("TMP3.TMP"); Ticks = clock (); Copy (vstrings.begin (), vstrings.end (), ostream_iterator Ticks = clock () - ticks; Cout << "ITERATING Vector:" << Ticks << endl; Ticks = clock (); Copy (dstrings.begin (), dstrings.end (), Ostream_iterator Ticks = clock () - ticks; Cout << "ITERATING DEQEUE: << Ticks << endl; Ticks = clock (); Copy (lstrings.begin (), lstrings.end (), Ostream_iterator Ticks = clock () - ticks; COUT << "ITERATING LIST: << Ticks << Endl; } ///: ~ The test used is a three thousand lines of text. Test Results: Read Into Vector: 690000 Read Into Deque: 680000 Read Into List: 690000 ITERATING Vector: 20000 ITERATING DEQEUE: 20000 ITERATING List: 10000 The file used by the test is a two thousand lines of text. Read Into Vector: 460000 Read Into Deque: 460000 Read Into List: 440000 ITERATING Vector: 10000 ITERATING DEQEUE: 10000 ITERATING List: 20000 The test used is a thousand lines of text. Test Results: Read Into Vector: 230000 Read Into Deque: 240000 Read Into List: 250000 ITERATING Vector: 10000 ITERATING DEQEUE: 0 ITERATING List: 10000 BEYOND_ML comment: This is difficult, what do you say? At the time of Push_Back, the smaller the file, the more you account for the Vector, the larger the file, the more you take it. Haha, joke, if you study, if you do, you don't do it. In fact, this is the result of the above test, the bigger the file, the more expensive, the reason is very simple, he wants Keeping new memory space to move yourself, and DEQUE is much better, because he doesn't have to move, he just needs a small rearrangement. And List is more problematic, his memory space is discrete. Can you understand this? So as a function of the function itself is not big, but now it seems that if other factors are involved, it will be said. At the point of view of reading data, the performance of List is very confused, I still can't think of any good explanation, maybe and the host's memory status when running. The performance of Vector and List can be said that it is not divided, but my personal point is that the vector must be better because his memory is continuous. So the third game, the performance of the three has a thousand autumn.