muduo ptr_vector详解

1. 简介

ptr_vector析构的时候会析构自己开辟出来的存放指针的空间,同时析构指针本身指向的空间而一般容器不会析构指针本身指向的空间,可参考boost::ptr_vector。

2. 类与接口
#ifndef _PTR_VECTOR_HH
#define _PTR_VECTOR_HH

#include <vector>
#include <memory>
#include <assert.h>

namespace myself
{

#define ASSERT(If, Msg) \
	if(!(If)) \
	{\
		fprintf(stderr, "Error/(%s, %d): %s, abort.\n", __FILE__, __LINE__, Msg); abort();\
	}

template<typename T>
class ptr_vector
{
public:
	typedef unsigned int size_type;
	typedef std::vector<T*> vector;
	typedef T* value_type;
	typedef value_type& reference;

	explicit ptr_vector()
	{
	}

	//ptr_vector析构的时候会析构自己开辟出来的存放指针的空间,同时析构指针本身指向的空间
	//而一般容器不会析构指针本身指向的空间
	~ptr_vector()
	{
		clear();
	}

	void clear()
	{
		if(!m_vector.empty()) {
			//typename vector::iterator it;
			for(auto it = m_vector.begin(); it != m_vector.end(); ++it) {
				delete *it;//释放指针指向的内存.
			}
		}

		m_vector.clear();//释放指针本身.
	}

	//在尾部追加元素
	//unique_ptr对象包装一个原始指针,并负责其生命周期。
	//当该对象被销毁时,会在其析构函数中删除关联的原始指针,防止内存泄漏
	void push_back(T* const &v)
	{
		ASSERT(v, "NULL point at ptr_vector push_back()");
		std::unique_ptr<T> tmp(v);
		m_vector.push_back(v); //使用 unique_ptr 保证push_back失败时,v也能正常释放.
		tmp.release();
	}

	//删除最后一个元素并返回指向删除对象的指针
	std::unique_ptr<T> pop_back()
	{
		ASSERT( !m_vector.empty(), "'pop_back()' on empty container");
		std::unique_ptr<T> tmp(m_vector.back());
		m_vector.pop_back();
		return std::move(tmp);
	}

	//提供像c数组通过下表访问的方法
	reference operator[](size_type n)
	{
		ASSERT(n < size(), "operator[] n out of the border")
		return m_vector[n];
	}

	bool empty()
	{
		return m_vector.empty();
	}

	size_type size()
	{
		return m_vector.size();
	}

	void reserve(size_type n)
	{
		m_vector.reserve(n);
	}

	void resize(size_type s)
	{
		size_type size = this->size();
		if(s < size) {
			for(auto it = m_vector.begin() + s; it != m_vector.end(); ++it) {
				delete *it;//释放指针指向的内存.
			}
			m_vector.resize(s);
		} else if(s > size) {
			for(; size != s; ++size) {
				push_back(new T);
			}
		}
		ASSERT(s == this->size(), "'resize' error size asymmetry");
	}

	void swap(ptr_vector<T>& v)
	{
		m_vector.swap(v.base());
	}

private:
	//将拷贝构造和赋值  设置为私有方法,防止所有权转移
	ptr_vector<T>& operator=(const ptr_vector<T>&);
	ptr_vector<T>(ptr_vector<T>&);

	vector& base()
	{
		return m_vector;
	}

	vector m_vector;
};

}

#endif
3. 使用
//
//  test_ptrvector.cc
//  test_ptrvector
//
//  Created by blueBling on 22-04-13.
//  Copyright (c) 2022年blueBling. All rights reserved.
//


#include "ptr_vector.h"

#include <ctime>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

using std::cout;
using std::endl;
using std::shared_ptr;
using std::unique_ptr;
using std::string;
using std::vector;

//https://www.cnblogs.com/my_life/articles/5452342.html
//https://www.bbsmax.com/A/kvJ3pKKw5g/
//https://www.codeproject.com/Articles/7351/ptr-vector-A-Container-For-Pointers

class TSomeData {
  private:
	int data;
  public:
	TSomeData(int d)
		: data(d) {
		// Empty
	}
};

const int TEST_ITERATIONS = 10000000;

typedef vector<unique_ptr<TSomeData>> TVectorOfUnique;
typedef vector<shared_ptr<TSomeData>> TVectorOfShared;
typedef myself::ptr_vector<TSomeData> TPtrVector;


int test_cmp2sharedptr() {

	clock_t start;
	clock_t end;

	start = ::clock();
	TVectorOfShared vectorOfShared;
	for (int i = 0; i < TEST_ITERATIONS; ++i) {
		// Test vector of shared_ptr
		shared_ptr<TSomeData> data(new TSomeData(i));
		vectorOfShared.push_back(data);
	}
	end = ::clock();

	cout << "Vector of shared:\n  Time executed: " 
	     << static_cast<uint32_t>((end - start) / (CLOCKS_PER_SEC/1000)) 
	     << endl;

	// ********************************************************************* //

	start = ::clock();
	TVectorOfUnique vectorOfUnique;
	for (int i = 0; i < TEST_ITERATIONS; ++i) {
	  unique_ptr<TSomeData> data(new TSomeData(i));
	  vectorOfUnique.push_back(std::move(data));
	}
	end = ::clock();

	cout << "Vector of unique:\n  Time executed: "
	     << static_cast<uint32_t>((end - start) / (CLOCKS_PER_SEC/1000)) 
	     << endl;

	// ********************************************************************* //

	start = ::clock();
	TPtrVector ptrVector;
	for (int i = 0; i < TEST_ITERATIONS; ++i) {
		// Test ptr_vector
		TSomeData* data = new TSomeData(i);
		ptrVector.push_back(data);
	}
	end = ::clock();

	cout << "PtrVector:\n  Time executed: "
	     << static_cast<uint32_t>((end - start) / (CLOCKS_PER_SEC/1000)) 
	     << endl;

	return 0;
}

int test_ptr_vector() {

	myself::ptr_vector<string> vec;
	vec.push_back (new string ("Hello, "));
	vec.push_back (new string ("world! "));

	//cout << vec[0]		 << vec.at(1)
	//     << *vec.begin() << vec.begin()[1]
	//    << vec.front()  << vec.back()
	//     << endl;

	cout << *vec[0] << endl;


	return 0;
}


int main() {

	test_cmp2sharedptr();

	test_ptr_vector();

	return 0;
}

-O0情况下测试结果(unique_ptr性能会好点)

Vector of shared:
  Time executed: 2106
Vector of unique:
  Time executed: 3198
PtrVector:
  Time executed: 1226
Hello, 
4. 源码

Github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值