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

  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;
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)//重写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 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;

}

/*
智能指针省去了我们释放指针的精力,但是也需要一定的开销。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 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
after push 3000000 int allocated
after pop 0 int allocated
===================int shared ptr for 3000000   11171
请按任意键继续. . .
*/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索指针
, 内存
, int
, 智能指针
, char
, std::move
, std
, std move
, memcpy s
, 左值c++std::move右值
, c++11智能指针
, 智能指针xmlc++指针释放
, ptr智能指针
void
智能指针 效率、c 智能指针、智能指针、c 11 智能指针、boost 智能指针,以便于您获取更多的相关知识。

时间: 2025-01-26 15:30:37

C++裸指针和智能指针的效率对比的相关文章

指针辨析:悬垂指针、哑指针、野指针、智能指针

悬垂指针:   1:提出的原因: 请看下面的代码片段: int *p=NULL; void main() { int i=10;p=&i; cout<<"第一次:*p = "<<*p<<endl; cout<<"第二次:*p = "<<*p<<endl; } int *p=NULL; void fun() {int i=10;p=&i;} void main() { fun();

智能指针问题-c++ 智能对象声明与堆内存,请明白人指点,谢谢

问题描述 c++ 智能对象声明与堆内存,请明白人指点,谢谢 定义 含有计数器的智能类模板如下: template class SmartObjectPtr { private: T* p; public: SmartObjectPtr(T* p_=NULL) : p(p_) { if (p) p->AddRef(); }; SmartObjectPtr(const SmartObjectPtr &p_) : p((T*)p_) { if (p) p->AddRef(); }; ~Sma

c++11教程 智能指针讲解

如果在程序中使用new从堆(自由存储区)分配内存,等到不需要时, 应使用delete将其释放.c++引入了智能指针auto_ptr, 以帮助自动完成这个过程. c++11摒弃了auto_ptr,并新增了三种智能指针:unique_ptr, shared_ptr, weak_ptr. 一. auto_ptr, unique_ptr , shared_ptr 头文件:  #include <memory> 用法:auto_ptr<double>  A(new double);uniqu

C++中智能指针如何设计和使用_C 语言

     智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露.它的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针.每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数:对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用

智能指针与弱引用详解_Android

在android 中可以广泛看到的template<typename T> class Sp 句柄类实际上是android 为实现垃圾回收机制的智能指针.智能指针是c++ 中的一个概念,因为c++ 本身不具备垃圾回收机制,而且指针也不具备构造函数和析构函数,所以为了实现内存( 动态存储区) 的安全回收,必须对指针进行一层封装,而这个封装就是智能指针,其实说白了,智能指针就是具备指针功能同时提供安全内存回收的一个类.当然,智能指针的功能还不只这些,想了解更多大家可以去研究下- 智能指针有很多实现

C++面试题(四)——智能指针的原理和实现

C++面试题(一).(二)和(三)都搞定的话,恭喜你来到这里,这基本就是c++面试题的最后一波了.      1,你知道智能指针吗?智能指针的原理.      2,常用的智能指针.      3,智能指针的实现. 1答案:智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针.智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放,      2, 最常用的智能指针:                1)std::auto_ptr,有很多问题. 不支持复制(拷贝

智能指针学习笔记

1. 介绍 本文介绍智能指针的使用.智能指针是c++ 中管理资源的一种方式,用智能指针管理资源,不必担心资源泄露,将c++ 程序员 从指针和内存管理中解脱出来,再者,这也是c++发展的趋势(这话不是我说的,见<Effective c++>和<c++实践编程>),应该认真学习一下. 智能指针中,最有名的应该数auto_ptr,该智能指针已经被纳入标准库,只需要包含<memory>头文件即可以使用,另外,TR1文档定义的shared_ptr和weak_ptr也已经实现(我用

智能指针与弱引用详解

在android 中可以广泛看到的template<typename T> class Sp 句柄类实际上是android 为实现垃圾回收机制的智能指针.智能指针是c++ 中的一个概念,因为c++ 本身不具备垃圾回收机制,而且指针也不具备构造函数和析构函数,所以为了实现内存( 动态存储区) 的安全回收,必须对指针进行一层封装,而这个封装就是智能指针,其实说白了,智能指针就是具备指针功能同时提供安全内存回收的一个类.当然,智能指针的功能还不只这些,想了解更多大家可以去研究下- 智能指针有很多实现

C++ 智能指针深入解析

以下是对C++中智能指针的使用进行了详细的分析介绍,需要的朋友可以参考下   1. 为什么需要智能指针?简单的说,智能指针是为了实现类似于Java中的垃圾回收机制.Java的 垃圾回收机制使程序员从繁杂的内存管理任务中彻底的解脱出来,在申请使用一块内存区域之后,无需去关注应该何时何地释放内存,Java将会自动帮助回收. 但是出于效率和其他原因(可能C++设计者不屑于这种傻瓜氏的编程方式),C++本身并没有这样的功能,其繁杂且易出错的内存管理也一直为广大程序员所诟 病. 更进一步地说,智能指针的出