欢迎来到山村网

C++裸指针和智能指针的效率对比

2019-03-02 11:02:34浏览:306 来源:山村网   
核心摘要:1.unique_ptr与queue连用,unique_ptr的使用特点:不能使用拷贝构造函数,拷贝赋值函数,但是可以使用move构造函数和move赋值函

1.unique_ptr与queue连用,unique_ptr的使用特点:不能使用拷贝构造函数,拷贝赋值函数,但是可以使用move构造函数和move赋值函数。

2.std::move的使用,可以将左值表达式强制转化成为右值表达式

3. 重载new操作符调试内存使用情况,因为心里不是很放心(智能指针真的为我释放了内存么?)所以尝试了重写new delete操作符。

4. 得到的结果是raw_ptr:unique_ptr:shared_ptr的性能是5:7:11,可见智能指针的效率还是相当诱人。

#include <iostream>#include <memory>#include <Windows.h>#include <queue>#include <Psapi.h>using namespace std;static size_ts_my_int_count = 0;const  intMAX_LOOP_ = 3000000;const int      NORMAL_FLAG = 0x12ff0101;const int   MY_INT_FLAG = 0x12ff0102;void* operator new(std::size_t size)throw(std::bad_alloc)//重写new操作符为的是统计我们关心的内存分配{int addLen = sizeof(size_t);void * p = std::malloc(addLen + 4 + size) ;if (!p)throw std::bad_alloc() ;memcpy(p, &size, addLen);//标志实际长度memcpy((char*)p + addLen, &NORMAL_FLAG, 4);//标志类型,普通---0x12ff0101, 我自己的int---0x12ff0102, 我自己的char[]---0x12ff0103return ((char*)p + addLen + 4);}void* operator new(std::size_t size, int flag)throw(std::bad_alloc)// 对应于调用 “new(MY_INT_FLAG) int” 这样所有我们关心的内存多可以被监视{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 ++;//统计关心的内存申请次数}memcpy(p, &size, addLen);//标志实际长度memcpy((char*)p + addLen, &flag, 4);//放置标志位,标志类型,普通---0x12ff0101, 我自己的int---0x12ff0102, 我自己的char[]---0x12ff0103return ((char*)p + addLen + 4);}void operator delete(void * q) throw(){void* p;int addLen = sizeof(size_t);p = (char*)q - addLen - 4;//还原原来的指针位置,p是真正的系统malloc出来的指针int flag;memcpy(&flag, (char*)p + addLen, 4);//得到标志位if (flag == MY_INT_FLAG){//统计关心的内存释放次数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;//注意需要手动释放count ++;}cout << "after pop " << s_my_int_count << " int allocated"<< endl;cout << "===================raw int ptr for " << count << "t" << GetTickCount() - start << endl;unique_ptr<int> q(new int);unique_ptr<int> r = move(q);// 编译正确,r(q) 和 r = q则编译失败,因为unique_ptr已经不允许使用“拷贝构造函数”queue<unique_ptr<int>> intUniQueue;//因为unique_ptr没有“拷贝构造函数”  copy-constructor//所以push()的参数不能是“左值”,左值会调用“拷贝构造函数”//只能是“右值”,右值则会调用“移动构造函数” move-constructor,  //std::move()函数可以强制将左值转化成为右值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));//因为p不是“右值”,所以我们需要“显式”的调用move将p强制转为右值。}cout << "after push " << s_my_int_count << " int allocated"<< endl;while (!intUniQueue.empty()){unique_ptr<int> p = std::move(intUniQueue.front());//queue.front() 是一个左值引用,即queue.front()=2 合法。intUniQueue.pop();count ++;}cout << "after pop " << s_my_int_count << " int allocated"<< endl;cout << "===================int unique  ptr for " << count << "t" << GetTickCount() - start << 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;}
(责任编辑:豆豆)
下一篇:

使用Perl编写CGI时需要注意的几个问题

上一篇:

Java获取特殊目录或特殊值

  • 信息二维码

    手机看新闻

  • 分享到
打赏
免责声明
• 
本文仅代表作者个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,作者需自行承担相应责任。涉及到版权或其他问题,请及时联系我们 xfptx@outlook.com