1.unique_ptr with the queue, UNIQUE_PTR features: You cannot use copy constructors to copy assignment functions, but you can use the move constructor and move assignment functions.
Using 2.std::move, you can force a left-valued expression to be a right-value expression
3. Overload new operator debugging memory usage, because the mind is not very reassuring (smart pointers really freed me for my memory?) Therefore, you attempted to override the new delete operator.
4. The result is that the performance of the raw_ptr:unique_ptr:shared_ptr is 5:7:11, and the efficiency of the smart pointer is still quite tempting.
#include <iostream> #include <memory> #include <Windows.h> #include <queue> #include <
Psapi.h> using namespace std;
static size_t S_my_int_count = 0;
const int MAX_LOOP_ = 3000000;
const int normal_flag = 0X12FF0101;
const int my_int_flag = 0x12ff0102;
void* operator new (std::size_t size) throw (std::bad_alloc)//rewrite the new operator to count the memory allocations we care about {int addlen = sizeof (size_t);
void * p = std::malloc (Addlen + 4 + size);
if (!p) throw Std::bad_alloc (); memcpy (P, &size, Addlen)//logo actual length memcpy ((char*) p + addlen, &normal_flag, 4);//flag type, normal---0x12ff0101,
my own int---0x12ff0102, my own char[]---0x12ff0103 return ((char*) p + Addlen + 4);
void* operator new (std::size_t size, int flag) throw (std::bad_alloc)//corresponds to calling "New (my_int_flag) int" so that all the memory we care about can be monitored {
int addlen = sizeof (size_t);
void * p = std::malloc (Addlen + 4 + size);
if (!p) throw Std::bad_alloc (); if (flag = = My_int_flag) {S_my_int_count ++;//counts the number of memory requests} memcpy (P, &Size, Addlen);//Mark Actual length memcpy ((char*) p + addlen, &flag, 4);//place flag bit, flag type, ordinary---0x12ff0101, my own int---0x12ff0102,
My own char[]---0x12ff0103 return ((char*) p + Addlen + 4);
} void operator delete (void * q) throw () {void* p;
int addlen = sizeof (size_t);
p = (char*) q-addlen-4;//restores the original pointer position, p is the real system malloc out of the pointer int flag;
memcpy (&flag, (char*) p + addlen, 4)//Get flag bit if (flag = = My_int_flag) {//Statistical care of the number of memory releases S_my_int_count-;
} if (p) std::free (p);
} void Main () {queue<int*> intqueue;
int count = 0;
Count = 0;
cout << "before push" << s_my_int_count << "int allocated" << Endl;
Longlong start = GetTickCount ();
for (int i = 0; i < max_loop_ i + +) {int* p = new (my_int_flag) int;
Intqueue.push (P);
cout << "After push" << s_my_int_count << "int allocated" << Endl;
while (!intqueue.empty ()) {int* p = intqueue.front ();
Intqueue.pop ();
Delete p;//Note that you need to manually release count + +; } cout << "afterPop "<< s_my_int_count << int allocated" << Endl; cout << "===================raw int ptr for" << count << "T" << GetTickCount ()-Start << E
Ndl
unique_ptr<int> q (new int); unique_ptr<int> r = Move (q);//compile correctly, R (q) and r = Q compile fails because unique_ptr is not allowed to use copy constructor queue<unique_ptr<int>& Gt intuniqueue;//because Unique_ptr does not have a "copy constructor" Copy-constructor//So the argument for push () cannot be "left", the left value calls "copy constructor"/Only "right" and the right value calls "move constructor"
Move-constructor, the//std::move () function can force the left value to be converted to the right value count = 0;
Start = GetTickCount ();
cout << "before push" << s_my_int_count << "int allocated" << Endl;
for (int i = 0; i < max_loop_ i + +) {unique_ptr<int> P (new (my_int_flag) int);
Intuniqueue.push (Std::move (P));//Because P is not a "right value", we need an "explicit" call move to force p to the right.
cout << "After push" << s_my_int_count << "int allocated" << Endl; while (!intuniqueue.empty ()) {unique_ptr<int> p = std::move (intuniqueUe.front ());//queue.front () is a left-value reference, that is, Queue.front () =2 legal.
Intuniqueue.pop ();
Count + +;
cout << "after Pop" << s_my_int_count << "int allocated" << Endl; cout << "===================int unique ptr for" << count << "T" << GetTickCount ()-Start <&L T
Endl
Queue<shared_ptr<int>> Intsharedqueue;
Count = 0;
Start = GetTickCount ();
cout << "before push" << s_my_int_count << "int allocated" << Endl;
for (int i = 0; i < max_loop_ i + +) {shared_ptr<int> P (new (my_int_flag) int);
Intsharedqueue.push (P);
cout << "After push" << s_my_int_count << "int allocated" << Endl;
while (!intsharedqueue.empty ()) {Auto P = intsharedqueue.front ();
Intsharedqueue.pop ();
Count + +;
cout << "after Pop" << s_my_int_count << "int allocated" << Endl; cout << "===================int shared ptr for" << count <<T "<< GetTickCount ()-Start << Endl; }/* The smart pointer saves us the effort to release the pointer, but it also requires a certain amount of overhead.
The cost of unique_ptr is much smaller than that of shared_ptr.
If a resource at every moment as long as there is a dominant, we would prefer to use unique_ptr bar, the efficiency is much higher. Before push 0 int allocated after push 3000000 int allocated after POPs 0 int allocated ===================raw int ptr for 3000000 5375 before push 0 int allocated after push 3000000 int allocated after pop 0 int allocated =================
==int unique ptr for 3000000 7313 before push 0 int allocated over push 3000000 int allocated after pop 0 int allocated ===================int shared ptr for 3000000 11171 Press any key to continue ... *