展会信息港展会大全

C++裸指针和智能指针的效率对比
来源:互联网   发布日期:2016-01-19 13:00:09   浏览:1917次  

导读:1 unique_ptr与queue连用,unique_ptr的使用特点:不能使用拷贝构造函数,拷贝赋值函数,但是可以使用move构造函数和move赋值函数。2 std::move的使用,可以将左值表达式强制转化成为右值表达式3 重载new操作符 ...

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_t s_my_int_count = 0;

constint MAX_LOOP_ = 3000000;

const intNORMAL_FLAG = 0x12ff0101;

const intMY_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[]---0x12ff0103

return ((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[]---0x12ff0103

return ((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 uniqueptr 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;

}

/*

智能指针省去了我们释放指针的精力,但是也需要一定的开销。unique_ptr 的开销相对于shared_ptr要小很多。

如果一个资源每个时刻都只要有一个支配者,我们还是优先使用unique_ptr吧,效率会高很多。

before push 0 int allocated

after push 3000000 int allocated

after pop 0 int allocated

===================raw int ptr for 30000005375

before push 0 int allocated

after push 3000000 int allocated

after pop 0 int allocated

===================int uniqueptr for 30000007313

before push 0 int allocated

after push 3000000 int allocated

after pop 0 int allocated

===================int shared ptr for 300000011171

请按任意键继续. . .

*/

赞助本站

人工智能实验室

相关热词: 裸指针 智能指针 C++

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港