c++ string类的完整实现!!!

COMSOL网格划分技巧总结 在对马赫曾德尔型光学传感器进行模拟仿真时,在采用自动物理场自动控制网格-极细化的情况下透射谱曲线仍不理想,因此需要手动划分网格来对其进行更精细的剖分。 手动划分的基本原则是在作用边界,热点,曲边处做细致划分, 基底,包层等做粗略划分。对于光波导型的微纳结构,在仿真时一般需要用到创建边界层网格。 1.COMSOL所需要的网格数量 网格单元数越多,结果精细度越高,计算所需内存越多。在细化到一定程度后网格收敛,仿真结果提升不明显。 2.网格剖分类型 ... 阅读详情

本文实现了c++ STL中的basic_string模板类,当然,通过typedef也就实现了string类和wstring类,限于篇幅,实现代码中用到了标准库的char_traits模板类,本人自己也实现了

char_traits模板类,为此还写了一篇博客,在我的博客里可以找到,那里的代码完全可以用在这里的basic_string类的实现中,当然,具体加到代码中要稍加改动,以和与basic_string类相关的全局模板函数兼容,如operator >> 模板函数的重载。

经过测试,这里的是实现在效率上不输标准库(与vs2012比对),代码注释还算清晰,而且具有良好的扩充性,可以以此量身打造自己的精简版本string。

好了,废话不多说了!看代码!!!

还请高手们不吝赐教!!!


此文件我建议命名为local_string.h,还是我一惯的习惯,封装于名字空间mystd中。

如果要测试代码,直接复制下面的代码就可以了,都在一个文件中。

标准库有的功能,这里基本上都有!




/*
*看完《STL源码剖析》后就有重写STL的冲动,这个basic_string的实现还算完整,
标准库有的功能,这里基本都有,如果有需要,可以在此基础上扩展功能!!!
大家如有发现bug,请与我联系,以使代码不断地完善!!!
*大家交流交流,谢谢!
* 邮箱:sunkang2101024@foxmail.com
*/


// 建议此文件命名为 "local_string.h"

// vs2012 调试通过
#pragma once 
#ifndef MYSTD_STRING_H_EX
#define MYSTD_STRING_H_EX
#include<cassert> // assert
#include<cstddef> // std::size_t,std::ptrdiff_t
#include<memory> // std::allocator 
#include<cstdlib> // rand()
#include<exception>  // std::out_of_range 
#include<iostream> //basic_istream, basic_ostream 



#define MYSTD_BEGIN namespace mystd {
#define MYSTD_END   }
  

// mystd 
#ifdef __cplusplus
MYSTD_BEGIN 
/////////////
//随机访问迭代器
template<class random_access_iterator, class Value_type, class Reference,class Difference_type>
 class reverse_random_access_iterator{
 public:
	 typedef Value_type value_type;
	 typedef value_type* pointer;
	 typedef Reference reference;
	 typedef Difference_type difference_type;
	 typedef std::size_t size_type;
	 typedef std::random_access_iterator_tag reverse_iterator_category;
 public:
	 random_access_iterator iterator;
	 typedef reverse_random_access_iterator self;
 public:
	 reverse_random_access_iterator()
	 {
		 //default constructor 
	 }
	 explicit reverse_random_access_iterator(const random_access_iterator& tmp):iterator(tmp)
	 {
		 //constructor  
	 }
	 reverse_random_access_iterator(const self& tmp):iterator(tmp.iterator)
	 {
		 // copy constructor 
	 }
	 template<class random_access_iterator, class Value_type, class Reference,class Difference_type>
	 reverse_random_access_iterator(const reverse_random_access_iterator<random_access_iterator,Value_type,Reference,Difference_type>& obj)
		 :iterator(obj.iterator)
	 {
		 // 此构造函数主要为了进行转换之用,
		 //reverse_iterator转换为 const_reverse_iterator 
	 }
	 self& operator = (const self& tmp)  // 可以不定义,直接使用默认的函数
	 {
		 iterator = tmp.iterator;
		 return *this;
	 }
	 ~reverse_random_access_iterator()
	 {
		 // do nothing 
	 }

	 self& operator ++ () 
	 {
		 --iterator;
		 return *this;
	 }
	 self operator ++ (int)
	 {
		 self tmp(*this);
		 ++*this;
		 return tmp;
	 }
	 self& operator -- ()
	 {
		 ++iterator;
		 return *this;
	 }
	 self operator -- (int)
	 {
		 self tmp(*this);
		 --*this;
		 return tmp;
	 }

	 self operator + (difference_type n) const 
	 {
		 return self(iterator - n);
	 }
	 self operator - (difference_type n) const 
	 {
		 return *this + (-n);
	 }
	 self& operator += (difference_type n) 
	 {
		 iterator -= n;
		 return *this;
	 }
	 self& operator -= (difference_type n) 
	 {
		 iterator += n;
		 return *this;
	 }
	 reference operator * () const 
	 {
		 return *(iterator - 1);
	 }
	 bool operator == (const self& tmp) const 
	 {
		 return iterator == tmp.iterator;
	 }
	 bool operator != (const self& tmp) const 
	 {
		 return !(*this == tmp);
	 }
	 bool operator < (const self& tmp) const 
	 {
		 return tmp.iterator < iterator;
	 }
	 bool operator <= (const self& tmp) const 
	 {
		  return tmp.iterator <= iterator;
	 }
	 bool operator > (const self& tmp) const 
	 {
		 return iterator < tmp.iterator;
	 }
	 bool operator >= (const self& tmp) const 
	 {
		  return iterator <= tmp.iterator;
	 }
	 random_access_iterator base() const 
	 {
		 return iterator;
	 }
	 friend difference_type operator - (const self& tmp_1,const self& tmp_2)
	 {
		 return tmp_2.iterator - tmp_1.iterator;
	 }
 };

 template<class T, class Reference,class Difference_type>
 class random_access_iterator{  // 反向随机访问迭代器
 public:
	 typedef T value_type;
	 typedef value_type *pointer;
	 typedef Reference reference;
	 typedef Difference_type difference_type;
	 typedef std::size_t size_type;
	 typedef std::random_access_iterator_tag iterator_category;
 public:
	 pointer ptr;
	 typedef random_access_iterator self;
 public:
	 random_access_iterator()
	 {
	 }
	 explicit random_access_iterator(pointer tmp):ptr(tmp)
	 { 
	 }
	 random_access_iterator(const self& tmp):ptr(tmp.ptr)
	 {
	 }
	 template<class T, class Reference,class Difference_type>
	 random_access_iterator(const random_access_iterator<T,Reference,Difference_type>& obj)
		 :ptr(obj.ptr)
	 {
		 // 此构造函数主要为了进行转换之用,
		 //iterator转换为 const_iterator 
	 }
	 self& operator = (const self& tmp)
	 {
		 ptr = tmp.ptr;
		 return *this;
	 }
	 ~random_access_iterator()
	 {
	 }

	 self& operator ++ ()
	 {
		 ++ptr;
		 return *this;
	 }
	 self operator ++ (int)
	 {
		 self tmp(*this);
		 ++*this;
		 return tmp;
	 }
	 self& operator -- ()
	 {
		 --ptr;
		 return *this;
	 }
	 self operator -- (int)
	 {
		 self tmp(*this);
		 --*this;
		 return tmp;
	 }
	 reference operator * () const // 足够的自由度
	 {
		 return *ptr;
	 }
	 bool operator == (const self& tmp) const 
	 {
		 return ptr == tmp.ptr;
	 }
	 bool operator != (const self& tmp) const 
	 {
		 return !(*this == tmp);
	 }

	 bool operator < (const self& tmp) const 
	 {
		 return ptr < tmp.ptr;
	 }
	 bool operator <= (const self& tmp) const 
	 {
		 return ptr <= tmp.ptr;
	 }
	 bool operator > (const self& tmp) const 
	 {
		 return tmp.ptr < ptr;
	 }
	 bool operator >= (const self& tmp) const 
	 {
		 return tmp.ptr <= ptr;
	 }
	 self operator + (difference_type n) const 
	 {
		 return self(ptr + n);
	 }
	 self operator - (difference_type n) const 
	 {
		 return *this + (-n);
	 }
	 self& operator += (difference_type n)
	 {
		 ptr += n;
		 return *this;
	 }
	 self& operator -= (difference_type n)
	 {
		 ptr -= n;
		 return *this;
	 }
	 friend difference_type operator - (const self& tmp_1,const self& tmp_2)
 	 {
		 return tmp_1.ptr - tmp_2.ptr;
	 }
 };

////////////////////////
 //限于篇幅,这里的char_traits模板类用的是标准库的,
 //我的博客里有一篇文章是关于char_traits模板类的实现的,完全可以用在这里。
 //
	template<class charT,class traits_type = std::char_traits<charT>,class Alloc = std::allocator<charT> >
class basic_string
{
public:
	typedef mystd::random_access_iterator<charT,charT&,std::ptrdiff_t> iterator;
	typedef mystd::random_access_iterator<const charT,const charT&,std::ptrdiff_t> const_iterator;
	typedef mystd::reverse_random_access_iterator<iterator,charT,charT&,std::ptrdiff_t> reverse_iterator;
	typedef mystd::reverse_random_access_iterator<const_iterator,const charT,const charT&,std::ptrdiff_t> const_reverse_iterator;
	typedef typename iterator::value_type value_type;
	typedef typename iterator::reference reference;
	typedef typename iterator::pointer pointer;
	typedef typename iterator::size_type size_type;
	typedef typename iterator::difference_type difference_type;
	typedef typename iterator::iterator_category iterator_category;
	typedef typename const_iterator::reference const_reference;
	typedef typename const_iterator::pointer const_pointer;
	typedef Alloc allocator_type;
public: 
	static const size_type npos = size_type(-1);
private:  
	pointer start,finish,end_of_storage; //数据成员
	typedef basic_string self;  //私有类型
	allocator_type alloc;  // 分配器
private: // 内部使用函数
	size_type alloc_capacity(size_type old_size) const  // 容量分配函数
	{ //这个函数主要是为了方便修改分配方案,
	//可以按照需要修改,但是要确保返回值大于old_size,以此保证capacity()非空(看实现可知)
	// 提示:与c_str()的实现有关。
		if(old_size < 10)
			return 10;  //wstring 
		else if(old_size < 100)
			return old_size * 2;
		else if(old_size < 1024)
			return old_size + old_size / 10;
		else
			return old_size + rand() % 1024 + 1;
		//返回值得大于old_size
	}
	void fill_n(pointer first,size_type n,value_type val)
	{
		assert(first != 0);
		while(n--)
			*first++ = val;
	}
	void fill(pointer first,pointer last,value_type val)
	{
		assert(first != 0 && last != 0);
		while(first != last)
			*first++ = val;
	}
	
	iterator insert_aux(size_type pos,const self& str)
	{ //用于insert相关函数
		assert(pos <= size());
		if(str.empty())
			return iterator(start+pos);
		if(size()+str.size() > capacity()) // 不管this是否等于&str
		{
			size_type str_size = str.size(); // 
			size_type old_size = size();
			size_type capacity_size = alloc_capacity(size()+str_size);
			pointer new_start = alloc.allocate(capacity_size);
			traits_type::copy(new_start,start,pos);
			traits_type::copy(new_start+pos,str.start,str_size);
			traits_type::copy(new_start+pos+str_size,start+pos,old_size-pos);
			alloc.deallocate(start,capacity());
			start = new_start;
			finish = start + old_size+ + str_size; // 
			end_of_storage = start + capacity_size;
			return iterator(start+pos);
		}
		else if(this != &str)
		{
			traits_type::move(start+pos+str.size(),start+pos,size()-pos);
			traits_type::copy(start+pos,str.start,str.size());
			finish += str.size();
			return iterator(start+pos);
		}
		else
		{
           size_type len_left = pos;
		   size_type len_right = size() - pos;
		   traits_type::copy(start+len_left*2+len_right,start+len_left,len_right);
		   traits_type::copy(start+len_left,start,len_left);
		   traits_type::copy(start+len_left*2,start+len_left*2+len_right,len_right);
		   finish += str.size();
		   return iterator(start+len_left);
		}
	}
	iterator erase_aux(size_type first,size_type last)
	{ //用于erase函数
		assert(first <= last  && last <= size());
		if(first > size())
			throw std::out_of_range("invalid string position");
		if(first == last)
			return iterator(start+first);
		traits_type::copy(start+first,start+last,size()-last);
		finish -= last - first;
		return iterator(start+first);
	}
	void empty_init()
	{  //用于初始化
		size_type capacity_size = alloc_capacity(1);
		start = alloc.allocate(capacity_size); //分配一定的空间
		finish = start;
		end_of_storage = start + capacity_size;
	}
	void swap(pointer& x,pointer& y)
	{
		assert(x != 0 && y != 0);
		pointer temp = x;
		x = y;
		y = temp;
	}
	bool is_inside(const self& str,value_type val) const 
	{ // 后面的查找功能的函数会用到,如find_first_of()函数
		size_type n = str.size();
		for(size_type i = 0; i < n; ++i)
			if(traits_type::eq(str[i],val))
				return true;
		return false;
	}
public:
	basic_string():start(0),finish(0),end_of_storage(0)
	{
		assert(sizeof(value_type) <= sizeof(wchar_t));
		empty_init();
	}
	basic_string(size_type n,value_type val):start(0),finish(0),end_of_storage(0)
	{
		assert(sizeof(value_type) <= sizeof(wchar_t));
		size_type capacity_size = alloc_capacity(n);
		start = alloc.allocate(capacity_size);
		finish = start + n;
		end_of_storage = start + capacity_size;
		fill_n(start,n,val);
	}
	basic_string(const self& str,size_type pos,size_type len = npos)
	{
		assert(sizeof(value_type) <= sizeof(wchar_t));
		assert(pos <= str.size());
		if(str.empty())
			empty_init();
		else
		{
		if(len == npos || len > str.size()-pos)
			len = str.size() - pos;
		size_type capacity_size = alloc_capacity(len);
		start = alloc.allocate(capacity_size);
		traits_type::copy(start,str.start+pos,len);
		finish = start + len;
		end_of_storage = start + capacity_size;
		}
	}
	//这个构造函数不可用explicit关键字,后面大量用到此构造函数做隐式转换
     basic_string(const_pointer str):start(0),finish(0),end_of_storage(0)
	{
		assert(sizeof(value_type) <= sizeof(wchar_t) && str != 0);
		size_type str_size = traits_type::length(str);
		size_type capacity_size = alloc_capacity(str_size);
		start = alloc.allocate(capacity_size);
		traits_type::copy(start,str,str_size);
		finish = start + str_size;
		end_of_storage = start + capacity_size;
	}
	basic_string(const_pointer str,size_type n):start(0),finish(0),end_of_storage(0)
	{
      assert(sizeof(value_type) <= sizeof(wchar_t)  && str != 0);
	  size_type len = traits_type::length(str);
	  //标准库没有对长度进行调整(测试vs2012的运行结果可知),本人觉得应该加上,这样有更好的容错性
	  //当然,在str很大的时候,效率上会有点折扣(计算长度的时间花销上)
	  if(n > len)  
		  n = len;
	  size_type capacity_size = alloc_capacity(n);
	  start = alloc.allocate(capacity_size);
	  traits_type::copy(start,str,n);
	  finish = start + n;
	  end_of_storage = start + capacity_size;
	}
	template <class InputIterator>
	basic_string(InputIterator first,InputIterator last):start(0),finish(0),end_of_storage(0)
	{
		assert(sizeof(value_type) <= sizeof(wchar_t));
		size_type len = 0;
		InputIterator new_first = first;
		while(new_first != last) //用后自增测试时会出现一点问题
			++len, ++new_first;
		size_type capacity_size = alloc_capacity(len);
		start = alloc.allocate(capacity_size);
		finish = start + len;
		/*while(first != last)  
			*start++ = *first++;*/  
		while(last != first)  //用后自增测试时会出现一点问题
			*--finish = *--last;
		finish = start + len; // 复位
		end_of_storage = start + capacity_size;
	}
	basic_string(const self& tmp):start(0),finish(0),end_of_storage(0)
	{
		assert(sizeof(value_type) <= sizeof(wchar_t));
		start = alloc.allocate(tmp.capacity());
		finish = start + tmp.size();
		end_of_storage = start + tmp.capacity();
		traits_type::copy(start,tmp.start,tmp.size());
	}

	self& operator = (const self& tmp)
	{
		if(this == &tmp) // 防止自身复制
			return *this;
		clear();
		if(tmp.empty())
			return *this;
		if(capacity() >= tmp.capacity())
		{
			traits_type::copy(start,tmp.start,tmp.size());
			finish = start + tmp.size();
		}
		else
		{
			size_type capacity_size = alloc_capacity(tmp.size());
			alloc.deallocate(start,capacity()); // 释放原有空间
			start = alloc.allocate(capacity_size);
			traits_type::copy(start,tmp.start,tmp.size());
			finish = start + tmp.size();
			end_of_storage = start + capacity_size;
		}
		return *this;
	}
	self& operator = (value_type val)
	{
		clear(); // 不释放内存,看代码可知
		insert_aux(0,self(1,val));
		return *this;
	}
	~basic_string()
	{
		//alloc.deallocate(start,capacity());
		//由于capacity()实现上的缘故,这里用end_of_storage - start(看capacity代码可知)
		//当然,第二个参数事实上没有用,任意写一个数字都可
		alloc.deallocate(start,end_of_storage - start);
	}
public:
	size_type size() const throw() 
	{ //按照标准文档的要求,不抛出异常,以下同理可得,不再赘述!
		return finish - start;
	}
	size_type length() const throw()
	{
		return size();
	}
	size_type max_size() const  throw()
	{
		return size_type(-1) / sizeof(value_type) - 1;
	}
	size_type capacity() const throw()
	{ //这里的计算本来不应该减 1 的,有意这样做是为了确保留有一个字符的空间(包括宽字符),方便做
		 // C风格字符串的转换,写入空字符,用于成员函数c_str()
		return end_of_storage - start - 1;
	}
	bool empty() const throw()
	{
		return start == finish;
	}
	iterator begin() throw()
	{
		return iterator(start);
	}
	const_iterator begin() const  throw()
	{
		return const_iterator(start);
	}
	iterator end()  throw()
	{
		return iterator(finish);
	}
	const_iterator end() const throw()
	{
		return const_iterator(finish);
	}
	reverse_iterator rbegin()  throw()
	{
		return reverse_iterator(end());
	}
	const_reverse_iterator rbegin() const throw()
	{
		return const_reverse_iterator(end());
	}
	reverse_iterator rend()  throw()
	{
		return reverse_iterator(begin());
	}
	const_reverse_iterator rend() const  throw()
	{
		return const_reverse_iterator(begin());
	}
	reference operator [] (size_type n)  throw()
	{
		assert(n < size());
		return *(start + n);
	}
	const_reference operator [] (size_type n) const throw()
	{
		assert(n < size());
		return *(start + n);
	}
	reference at(size_type n) 
	{
		if(n < size())
			return *(start + n);
		else
			throw std::out_of_range("invalid string position");
	}
	const_reference at(size_type n) const 
	{
		if(n < size())
			return *(start + n);
		else
			throw std::out_of_range("invalid string position");
	}
	allocator_type get_allocator() const throw()
	{
		return allocator_type();
	}
	void reserve(size_type n = 0)
	{
		if(n <= capacity())
			;
		else
		{
			size_type capacity_size = alloc_capacity(n);
			size_type old_size = size();
			pointer new_start = alloc.allocate(capacity_size);
			traits_type::copy(new_start,start,size());
			alloc.deallocate(start,capacity());
			start = new_start;
			finish = start + old_size;
			end_of_storage = start + capacity_size;
		}
	}
	void clear() 
	{
		finish = start; //并不释放内存
	}
	self substr(size_type pos = 0,size_type len = npos) const
	{
		assert(pos <= size());
		return self(*this,pos,len); // 显式调用构造函数
	}
    self& insert(size_type pos,const self& str)
    {
		assert(pos <= size());
		insert_aux(pos,str);
		return *this;
    }
	const_pointer c_str() const  throw()
	{ //构造函数保证capacity() != 0,或者说start,finish,end_of_storage不为空指针
		//当然,这和具体的实现有关,这是我的一个实现
		*finish = 0;  // 转换成C风格的字符串
		return start;
	}
	const_pointer data() const throw()
	{ 
	    *finish = 0; 
		// 也可以直接返回start,标准文档没有强制要求为C风格字符串
		return start;
	}
    self& insert(size_type pos,const self& str,size_type subpos,size_type sublen)
	{
		assert(pos <= size());
		insert_aux(pos,str.substr(subpos,sublen));
		return *this;
	}
    self& insert(size_type pos,const_pointer str)
	{
		assert(pos <= size() && str != 0);
		insert_aux(pos,self(str));
		return *this;
	}
    self& insert(size_type pos,const_pointer str,size_type n)
	{
		assert(pos <= size() && str != 0);
		insert_aux(pos,self(str,n));
		return *this;
	}

    self& insert(size_type pos,size_type n,value_type val)
	{
		assert(pos <= size());
		insert_aux(pos,self(n,val));
		return *this;
	}
    void insert(iterator itr,size_type n,value_type val)
	{
		assert(itr >= begin() && itr <= end());
		insert_aux(itr-begin(),self(n,val));
	}
    iterator insert(iterator itr,value_type val)
	{
		assert(itr >= begin() && itr <= end());
		return insert_aux(itr-begin(),self(1,val));
	}
    template <class InputIterator>
    void insert(iterator itr,InputIterator first,InputIterator last)
	{
		assert(itr >= begin() && itr <= end());
		insert_aux(itr-begin(),self(first,last));
	}
	self& erase(size_type pos = 0,size_type len = npos)
	{
		assert(pos <= size());
		if(pos > size())
			throw std::out_of_range("invalid string position");
		if(len == npos || len > size()-pos)
			len = size() - pos;
		erase_aux(pos,pos+len);
		return *this;
	}

    iterator erase(iterator itr)
	{
		assert(itr >= begin() && itr < end());
		return erase_aux(itr-begin(),itr-begin()+1);
	}
    iterator erase(iterator first,iterator last)
	{
		assert(first >= begin() && first <= last && last <= end());
		return erase_aux(first-begin(),last-begin());
	}
	void push_back(value_type val)
	{
		insert_aux(size(),self(1,val));
	}
	self& append(const self& str)
	{
		return *this += str;
	}

    self& append(const self& str,size_type subpos,size_type sublen)
	{
		return *this += str.substr(subpos,sublen);
	}

    self& append(const_pointer str)
	{
		assert(str != 0);
		return *this += str;
	}

    self& append(const_pointer str,size_type n)
	{
		assert(str != 0);
		return *this += self(str,n);
	}

    self& append(size_type n,value_type val)
	{
		return *this += self(n,val);
	}

   template <class InputIterator>
   self& append(InputIterator first,InputIterator last)
   {
	   return *this += self(first,last);
   }
   self& assign(const self& str)
   {
	   return *this = str;
   }

   self& assign(const self& str,size_type subpos,size_type sublen)
   {
	  return *this = self(str,subpos,sublen);
   }

   self& assign(const_pointer str)
   {
	   assert(str != 0);
	   return *this = self(str);
   }

   self& assign(const_pointer str,size_type n)
   {
	   assert(str != 0);
	   return *this = self(str,n);
   }
   self& assign(size_type n,value_type val)
   {
	   return *this = self(n,val);
   }

   template <class InputIterator>
   self& assign(InputIterator first,InputIterator last)
   {
	  return *this = self(first,last);
   }
   void resize(size_type n)
   {
	   resize(n,0); //转调
   }
   void resize(size_type n,value_type val)
   {
	   if(n <= size())
		   finish -= size() - n;
	   else if(n <= capacity())
	   {
		   fill(finish,finish+n,val);
		   finish += n - size();
	   }
 	   else
	   {
		   size_type capacity_size = alloc_capacity(n);
		   pointer new_start = alloc.allocate(capacity_size);
		   traits_type::copy(new_start,start,size());
		   fill(new_start+size(),new_start+n,val);
		   alloc.deallocate(start,capacity());
		   start = new_start;
		   finish = start + n;
		   end_of_storage = start + capacity_size;
	   }
   }
   void swap(self& str)
   {
	   if(this == &str)
		   return ;
	   swap(start,str.start);
	   swap(finish,str.finish);
	   swap(end_of_storage,str.end_of_storage);
   }

   self& replace(size_type pos,size_type len,const self& str)
   {
	   assert(pos <= size());
	   if(pos > size())
		   throw std::out_of_range("invalid string position"); 
	   // 后面的replace重载函数就不用写异常了,因为都会直接或间接地调用到这个函数
	   if(len > size() - pos)
		   len = size() - pos;
	   if(size() + str.size() - len > capacity())
	   {    
		   size_type new_size = size()+str.size()-len;
		   size_type capacity_size = alloc_capacity(new_size);
		   pointer new_start = alloc.allocate(capacity_size);
		   traits_type::copy(new_start,start,pos);
		   traits_type::copy(new_start+pos,str.start,str.size());
		   traits_type::copy(new_start+pos+str.size(),start+pos+len,size()-pos-len);
		   alloc.deallocate(start,capacity());
		   start = new_start;
		   finish = start + new_size;
		   end_of_storage = start + capacity_size;
	   }
	   else if(this != &str)  //如果不是自身的替换
	   {
		   if(str.size() <= len)
		   {
			   traits_type::copy(start+pos,str.start,str.size());
			   erase(pos+str.size(),len-str.size()); // 长度len - str.size()
			   // finish 已经更新
		   }
		   else // size() + str.size() - len <= capacity() 
		   {
			   traits_type::move(start+pos+str.size(),start+pos+len,size()-pos-len);
			   traits_type::copy(start+pos,str.start,str.size());
			   finish += str.size() - len;
		   }
	   }
	   else
		   return replace(pos,len,self(str)); //递归调用,这次不会是自身了。
	  return *this;
   }
 
   self& replace(iterator itr_1,iterator itr_2,const self& str)
   {
	   assert(itr_1 >= begin() && itr_2 <= end());
	   return replace(itr_1-begin(),itr_2-itr_1,str); // 转调
   }
   self& replace(size_type pos,size_type len,const self& str,
                       size_type subpos,size_type sublen)
   {
	   assert(pos <= size());
	   return replace(pos,len,str.substr(subpos,sublen));
   }

   self& replace(size_type pos,size_type len,const_pointer str)
   {
	   assert(pos <= size() && str != 0);
	   return replace(pos,len,self(str));
   }
   self& replace(iterator itr_1,iterator itr_2,const_pointer str)
   {
	   assert(itr_1 >= begin() && itr_2 <= end());
	   return replace(itr_1,itr_2,self(str)); //转调
   }
   self& replace(size_type pos,size_type len,const_pointer str,size_type n)
   {
	   assert(pos <= size() && str != 0);
	   return replace(pos,len,self(str,n));
   }
   self& replace(iterator itr_1,iterator itr_2,const_pointer str,size_type n)
   {
	   assert(itr_1 >= begin() && itr_2 <= end() && str != 0);
	   return replace(itr_1,itr_2,self(str,n));
   }

   self& replace(size_type pos,size_type len,size_type n,value_type val)
   {
	   assert(pos <= size());
	   return replace(pos,len,self(n,val));
   }
   self& replace(iterator itr_1,iterator itr_2,size_type n,value_type val)
   {
	   assert(itr_1 >= begin() && itr_2 <= end());
	   return replace(itr_1,itr_2,self(n,val));
   }

  template <class InputIterator>
  self& replace(iterator itr_1,iterator itr_2,InputIterator first,InputIterator last)
  {
	  assert(itr_1 >= begin() && itr_2 <= end());
	  return replace(itr_1,itr_2,self(first,last));
  }
  int compare(const self& str) const
  { //后面的compare重载函数都间接调用此函数
	  if(this == &str)
		  return 0;
	  size_type num = size() >= str.size() ? size() : str.size();
	  return traits_type::compare(c_str(),str.c_str(),num); //需要转换为C风格字符串
  }
  int compare(size_type pos,size_type len,const self& str) const
  {
	  assert(pos <= size());
	  if(pos > size()) // 后面的重载函数不用写异常了,这里写了
		  throw std::out_of_range("invalid string position");
	  //size_type num = len >= str.size() ? len : str.size();
	  //return traits_type::compare(start+pos,str.start,num);
	  return substr(pos,len).compare(str);  //转调
  }
  int compare(size_type pos,size_type len,const self& str,
	  size_type subpos,size_type sublen) const
  {
	  assert(pos <= size());
	  return compare(pos,len,self(str,subpos,sublen)); //转调
  }

  int compare(const_pointer str) const
  {
	  assert(str != 0);
	  return compare(self(str));
  }
  int compare(size_type pos,size_type len,const_pointer str) const
  {
	  assert(pos <= size() && str != 0);
	  return compare(pos,len,self(str));
  }

  int compare(size_type pos,size_type len,const_pointer str,size_type n) const
  {
	  assert(pos <= size() && str != 0);
	  return compare(pos,len,self(str,n));
  }
  size_type copy(pointer str,size_type len,size_type pos = 0) const
  {
	  assert(pos <= size() && str != 0);
	  if(len + pos > size())
		  len = size() - pos; // 调整一下长度
	  traits_type::copy(str,start+pos,len);
	  return len;
  }
  size_type find(const self& str,size_type pos = 0) const throw()
  { //pos为搜索开始处,用数学区间表示为[pos,size() )
	  assert(pos <= size());
	  if(empty())
		  return npos;
	  size_type len_str = str.size();
	  size_type len = size() - pos; 
	  if(len < len_str)
		  return npos;
	  size_type end_pos = size() - len_str; // 调整了一下有效长度,避免做无用功
	  while(pos <= end_pos)
	  {
		  if(compare(pos,len_str,str) == 0) // 转调重载的成员函数
			  return pos;
		  else	
			  ++pos;
	  }
	  return npos;
  }

   size_type find(const_pointer str,size_type pos = 0) const throw()
   {
	   assert(pos <= size() && str != 0);
	   if(empty())
		  return npos;
	   return find(self(str),pos); // 转调重载的成员函数
   }

   size_type find(const_pointer str,size_type pos,size_type n) const throw()
   { //str中的n个字符,注意 n 的具体所指
	   assert(pos <= size() && str != 0);
	   if(empty())
		  return npos;
	   return find(self(str,n),pos);// 转调重载的成员函数
   }

   size_type find(value_type val,size_type pos = 0) const throw()
   {
	   assert(pos <= size());
	   if(empty())
		  return npos;
	   return find(self(1,val),pos); // 转调重载的成员函数
   }

   size_type rfind(const self& str,size_type pos = npos) const throw()
   {  // pos为搜索开始处,用数学区间表示为[0,pos]
	   	if(empty())
		   return npos;
	   if(pos == npos || pos >= size()) //加上pos == npos的判断并非多此一举
		   pos = size() - 1;
	   if(size() < str.size())
		   return npos;
	   size_type len_str = str.size();
	   if(pos > size() - len_str)
		   pos = size() - len_str;  // 调整位置,避免做无用的搜索
	   while(pos >= 0 && pos != size_type(-1))
	   {
		   if(compare(pos,len_str,str) == 0) // 转调成员函数
			   return pos;
		   else
		   --pos;
	   }
	   return npos;
   }

   size_type rfind(const_pointer str,size_type pos = npos) const throw()
   {
	   assert(str != 0);
	   if(empty())
		   return npos;
	   if(pos == npos || pos >= size()) //加上pos == npos的判断并非多此一举
	   pos = size() - 1;
	   return rfind(self(str),pos); // 转调重载的成员函数
   }

   size_type rfind(const_pointer str,size_type pos,size_type n) const throw()
   { // n为str需要搜索字符的个数,因为构造函数实现上的差异,我的n值在调用构造函数时会有调整,
	 // 这样是为了增强容错性,但是测试vs2012可知此实现上没有此功能,
	 //因此,用标准库时,依赖于用户使用正确的n值,否则会得不到预期的结果,
	 // 用我的这个实现,当n值大于str的长度时,会匹配整个str字符串
	   //类似情况同理可知,不再赘述。
	   assert(str != 0);
	   if(empty())
		   return npos;
	   if(pos >= size())
	   pos = size() - 1;
	   return rfind(self(str,n),pos); // 转调重载的成员函数
   }

   size_type rfind(value_type val,size_type pos = npos) const throw()
   { 
	   if(empty())
		   return npos;
	   if(pos == npos || pos >= size())
	   pos = size() - 1;
	   return rfind(self(1,val),pos); // 转调重载的成员函数
   }
   size_type find_first_of(const self& str,size_type pos = 0) const throw()
   { //pos为搜索开始处,用数学区间表示为[pos,size() )
	   assert(pos <= size());
	   if(empty())
		   return npos;
	   size_type end_pos = size();
	   while(pos != end_pos && !is_inside(str,*(start+pos)))
		   ++pos;
	   if(pos == end_pos)
		   return npos;
	   else
		   return pos;
   }

   size_type find_first_of(const_pointer str,size_type pos = 0) const throw()
   {  //pos为搜索开始处,范围为[pos,size() )
	   assert(pos <= size() && str != 0);
	   if(empty())
		   return npos;
	   return find_first_of(self(str),pos); // 转调重载的成员函数
   }

   size_type find_first_of(const_pointer str,size_type pos, size_type n) const throw()
   { //pos为搜索开始处,范围为[pos,size() )
	   assert(pos <= size() && str != 0);
	   if(empty())
		   return npos;
	   return find_first_of(self(str,n),pos); // // 转调重载的成员函数
   }

   size_type find_first_of(value_type val,size_type pos = 0) const throw()
   { //pos为搜索开始处,范围为[pos,size() )
	   assert(pos <= size());
	   if(empty())
		   return npos;
	   return find_first_of(self(1,val),pos); // 转调重载的成员函数
   }
   size_type find_last_of(const self& str,size_type pos = npos) const throw()
   {  //pos 搜索结束处,范围[0,pos],包含pos
	   if(empty())
		   return npos;
	   if(pos == npos || pos >= size()) //加上pos == npos的判断并非多此一举
		   pos = size() - 1;
	   while(pos >= 0 && pos != size_type(-1) && 
		   !is_inside(str,*(start+pos)))
		   --pos;
	   if(pos != size_type(-1))
		   return pos;
	   else
		   return npos;
   }

   size_type find_last_of(const_pointer str,size_type pos = npos) const throw()
   {  //pos 搜索结束处,范围[0,pos],包含pos
	   if(empty())
		   return npos;
	   assert(str != 0);
	   if(pos == npos || pos >= size())
		   pos = size() - 1;
	   return find_last_of(self(str),pos); // 转调重载的成员函数
   }

   size_type find_last_of(const_pointer str,size_type pos,size_type n) const throw()
   {  //pos 搜索结束处,范围[0,pos],包含pos
	   assert(str != 0);
	   if(empty())
		   return npos;
	   if(pos >= size())
		   pos = size() - 1;
	   return find_last_of(self(str,n),pos); // 转调重载的成员函数
   }

   size_type find_last_of(value_type val,size_type pos = npos) const throw()
   { //pos 搜索结束处,范围[0,pos],包含pos
	   if(empty())
		   return npos;
	   if(pos == npos || pos >= size())
		   pos = size() - 1;
	   return find_last_of(self(1,val),pos); // 转调重载的成员函数
   }
   size_type find_first_not_of(const self& str,size_type pos = 0) const throw()
   {    //pos 为搜索开始处,范围[pos,size() )
	   assert(pos <= size());
	   if(empty())
		   return npos;
	   size_type end_pos = size();
	   while(pos != end_pos && is_inside(str,*(start+pos)))
		   ++pos;
	   if(pos == end_pos)
		   return npos;
	   else
		   return pos;
   }
   size_type find_first_not_of(const_pointer str,size_type pos = 0) const throw()
   {  //pos 为搜索开始处,范围[pos,size() ) 
	   assert(pos <= size() && str != 0);
	   if(empty())
		   return npos;
	   return find_first_not_of(self(str),pos);
   }

   size_type find_first_not_of(const_pointer str,size_type pos,size_type n) const throw()
   { //pos 为搜索开始处,范围[pos,size() )
	   assert(pos <= size() && str != 0);
	   if(empty())
		   return npos;
	   return find_first_not_of(self(str,n),pos); // 转调重载的成员函数
   }

   size_type find_first_not_of(value_type val,size_type pos = 0) const throw()
   { //pos 为搜索开始处,范围[pos,size() )
	   assert(pos <= size());
	   if(empty())
		   return npos;
	   return find_first_not_of(self(1,val),pos);
   }
   size_type find_last_not_of(const self& str,size_type pos = npos) const throw()
  {  //pos 搜索结束处,范围[0,pos]
	  if(empty())
		  return npos;
	   if(pos == npos || pos >= size())
		   pos = size() - 1;
	   while(pos >= 0 &&  pos != size_type(-1) && 
		   is_inside(str,*(start+pos)))
		   --pos;
	   if(pos != size_type(-1))
		   return pos;
	   else
		   return npos;
   }
   size_type find_last_not_of (const_pointer str,size_type pos = npos) const throw()
  {  //pos 搜索结束处,范围[0,pos]
	  assert(str != 0);
	  if(empty())
		  return npos;
	  if(pos == npos || pos >= size()) //加上pos == npos的判断并非多此一举
		  pos = size() - 1;
	   return find_last_not_of(self(str),pos); // 转调重载的成员函数
   }

   size_type find_last_not_of (const_pointer str,size_type pos,size_type n) const throw()
  {  //pos 搜索结束处,范围[0,pos]
	   assert(str != 0);
	   if(empty())
		   return npos;
	   if(pos >= size())
		   pos = size() - 1;
	   return find_last_not_of(self(str,n),pos); // 转调重载的成员函数
   }

   size_type find_last_not_of (value_type val,size_type pos = npos) const throw()
   { //pos 搜索结束处,范围[0,pos]
	   if(empty())
		   return npos;
	   if(pos == npos || pos >= size())
		   pos = size() - 1;
	   return find_last_not_of(self(1,val),pos); // 转调重载的成员函数
   }
   self& operator += (const self& str)
   {
		insert_aux(size(),str);
		return *this;
   }
	self& operator += (value_type val)  
	{
		insert_aux(size(),self(1,val));
		return *this;
	}

	friend self operator + (const self& str1,const self& str2)
	{
		return self(str1) += str2;
	}
	friend self operator + (const self& str,value_type val)
	{
		return self(str) += self(1,val);
	}
	friend self operator + (value_type val,const self& str)
	{
		return self(1,val) += str;
	}
    friend void swap(self& str1,self& str2)
	{
		if(&str1 == &str2)
			return ;
		str1.swap(str2);
	}
	friend bool operator == (const self& str1,const self& str2)
	{
		return str1.compare(str2) == 0;
	}
	friend bool operator != (const self& str1,const self& str2)
	{
		return str1.compare(str2) != 0;
	}
	friend bool operator < (const self& str1,const self& str2)
	{
		return str1.compare(str2) < 0;
	}
	friend bool operator <= (const self& str1,const self& str2)
	{
		return str1.compare(str2) <= 0;
	}
	friend bool operator > (const self& str1,const self& str2)
	{
		return str1.compare(str2) > 0;
	}
	friend bool operator >= (const self& str1,const self& str2)
	{
		return str1.compare(str2) >= 0;
	}

};


template <class charT, class traits, class Alloc>
std::basic_istream<charT,traits>& operator >> (std::basic_istream<charT,traits>& is,
                                           mystd::basic_string<charT,traits,Alloc>& str)
{
	str.clear();  //先清空str
	int chr = 0;  //对wchar_t类型字符也适用
	while((chr = is.get()) && chr != ' ' && chr != '\n')
		str.push_back(chr);
	return is;
}


template <class charT, class traits, class Alloc>
 std::basic_ostream<charT,traits>& operator<< (std::basic_ostream<charT,traits>& os,
                                           const mystd::basic_string<charT,traits,Alloc>& str)
{
	typedef typename mystd::basic_string<charT,traits,Alloc>::size_type size_type;
	size_type size = str.size();
	for(size_type i = 0; i < size; ++i)
		os<<str[i];
	return os;

}

template <class charT, class traits, class Alloc>
std::basic_istream<charT,traits>& getline(std::basic_istream<charT,traits>& is,
                                 mystd::basic_string<charT,traits,Alloc>& str, charT delim)
{
	charT chr = 0;
	str.clear(); //先清空str
	while((chr = is.get()) && chr != delim && chr != '\n')
		str.push_back(chr);
	return is;
}

template <class charT, class traits, class Alloc>
std::basic_istream<charT,traits>& getline(std::basic_istream<charT,traits>& is,
                                 mystd::basic_string<charT,traits,Alloc>& str)
{
	charT chr = 0;
	str.clear(); //先清空str
	while((chr = is.get()) && chr != '\n')
		str.push_back(chr);
	return is;
}





 
typedef mystd::basic_string<char,std::char_traits<char>,std::allocator<char> > string;
typedef mystd::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > wstring;



MYSTD_END // end of namespace mystd 
#endif // __cplusplus 
#endif // MYSTD_STRING_H_EX


下面是一个简单的测试程序!并和标准库比对运行结果!以验证正确性!


#include<iostream>
#include<string>
#include<ctime>  //clock
#include"local_string.h"
#define STD mystd   //改为std可以运行标准库版本

//测试可知,结果与标准库的运行结果一样

using std::cout;
using std::wcout;
using std::cin;
using std::wcin;
using std::endl;

int main()
{  // 以下是一些测试代码!
	STD::string str;
	str = "ABCDEFGHIJK";  //11 个字符长度

	clock_t start = clock();
	
	//之所以选择在首部进行插入操作,是为了测试在极端条件下的运行效率!
    for(int i = 0; i < 25; ++i)
		str.insert(0,str);  
	//完成循环后,str会变得很大,大小为 11乘以2的25次方 ,结果为369,098,752个字符长度
	clock_t finish = clock();
/*
 在release版本下的统计结果如下:(运行时间/S)
 mystd        |       std 
--------------|--------------------           
 0.348        |       0.435
 0.366        |       0.446
 0.359        |       0.47
 0.392        |       0.46
 0.374        |       0.445
 可以看到,我的实现版本比标准库略快!
声明:我的机器是win8系统,vs2012  
*/
	cout<<double(finish - start) / CLOCKS_PER_SEC << "秒"<<endl;
	//str.size()的结果与标准库一样,str.capacity()不一样,
	//这个是正常的,capacity()的结果与具体的实现有关
	cout<<str.size()<<"\t"<<str.capacity()<<endl;
	str.swap(STD::string()); //显式释放内存

	//我的邮箱,希望不吝赐教!
	str.insert(0,"sunkang2101024@foxmail.com");

	//正确的输出结果是sunkang2101024
	cout<<str.erase(str.find_first_of('@',0))<<endl;


	//宽字符版本测试
	wcout<<STD::wstring(L"hello world").c_str()<<endl;
	STD::wstring wstr;
	wstr += L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	//测试反向迭代器
	for(STD::wstring::const_reverse_iterator first = wstr.rbegin(); first != wstr.rend(); ++first)
		wcout<<*first<<"\t";
	cout<<endl;

	//间接测试compare函数
	if(STD::string("hello world") == "hello world")
		cout<<"相等"<<endl;
	else
		cout<<"不相等"<<endl;

	//测试一下replace函数
	cout<<str.assign("hello world").replace(6,5,str)<<endl;
	cout<<str.replace(str.begin(),str.end(),"sunkang2101024@foxmail.com")<<endl;

	//测试重载的operator + 
	cout<<"HHHHHHH " + str + 'A' + "ABCDEFG"<<endl;

	// 测试异常
	try
	{  
		str.clear();
		cout<<str.at(100)<<endl;
		//此时会抛出异常
	}
	catch(std::out_of_range& ex)
	{
		cout<<ex.what()<<endl;
	}

	// 测试rfind函数
	str = "ABCDEFG   RSTUVQXYZ";
	STD::string::size_type pos = str.rfind("EFG",str.size(),2);
	//可以试着将函数的第三个参数取一个比较大的值,比如100,
	//在我的这个实现版本下,仍然会取得正确的结果,vs2012测试不行
	if(pos != STD::string::npos)
		cout<<str.substr(pos)<<endl;

	cout<<endl;
	system("pause");
	return 0;
}



望高手批评指正!!!谢谢!!!












相关推荐

NVIDIA DRIVE SDK学习(二)——NvMedia

可以通过使用NvSciBuf API通过NvMedia Tensor属性分配NvSciBuf来创建NvMedia张量。由于NvSciBuf API有助于NvMedia和NVIDIA®CUDA®之间的数据共享,这使得分配的张量可以在NvSciBuf API允许的情况下重复使用。它支持图像聚合操作。NvSciSync组件使得NvMedia组件可以与其他组件保持同步,比如CUDA组件、基于NvSciSync的组件等。立体视差模式:在这种模式下,该模块通过左图像和右图像来产生立体视差,从而进行物体深度测量。

weixin_39592381的博客 3044

C++异常处理

C++异常处理(try catch throw)——袁志文 程序运行时常会碰到一些异常情况,例如: 做除法的时候除数为 0; 用户输入年龄时输入了一个负数; 用 new 运算符动态分配空间时,空间不够导致无法分配; 访问数组元素时,下标越界;打开文件读取时,文件不存在。 这些异常情况,如果不能发现并加以处理,很可能会导致程序崩溃。 一发现异常情况就立即处理未必妥当,因为在一个函数执行过程中发生的异常,在有的情况下由该函数的调用者决定如何处理更加合适。尤其像库函数这类提供给程序员调用,用以完成与具体应用无

qq_42589025的博客 2103

新手必看!Stata工具变量分析中的三大陷阱:如何正确解读LM统计量、CDW检验和Hansen J值

本文深度解析Stata工具变量分析中的三大核心检验:不可识别检验、弱IV检验和过度识别检验,帮助新手避开常见陷阱。详细解读LM统计量、CDW检验和Hansen J值的正确使用方法,提供实战案例和Stata操作指南,确保研究结论的可靠性。

weixin_29231027的博客 571

C++ 编译错误std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >的两种解决办法

有时,使用Visual Studio Code编译C++程序,如果task.json文件引用参数配置不正确,也会报这个错误,只需要在配置文件中加入.h文件和.cpp文件路径即可。C++程序编译阶段有个常见的错误,std::__cxx11::basic_***,可能是string,list等,也许程序在其他环境完成编译,在运行环境报错,也许是正在编译阶段报错。比如Ubuntu环境,如果程序或依赖编译时版本和运行时gcc/g++版本不一致,就会报这个错误。如下,args参数的 “-I”(大写i)部分。

qqliang1314的专栏 1万+

Ubuntu22.04 网络图标消失与连接故障排查指南(附实战修复流程)

本文详细介绍了Ubuntu22.04系统中网络图标消失与连接故障的排查与修复方法。通过ifconfig、dhclient等命令诊断问题,提供从紧急恢复网络连接到深度排查的完整解决方案,帮助用户快速恢复网络功能并预防类似问题再次发生。

weixin_28481133的博客 287

告别重打包:在Android 9上实现免Root的Frida-Gadget持久化Hook(附AOSP源码修改详解)

本文详细介绍了在Android 9上实现免Root的Frida-Gadget持久化Hook技术方案。通过修改AOSP源码,绕过传统重打包方式面临的签名校验和完整性检查,实现在非Root环境下的系统级Hook。文章包含核心代码修改、编译配置调整及调试技巧,为移动安全研究提供高效稳定的解决方案。

weixin_33726313的博客 501

C++中string容器的元素访问

C++中string容器的元素访问

2301_76197086的博客 544

Python气象数据处理实战:用PyCINRAD轻松绘制雷达PPI图像(附避坑指南)

本文详细介绍了如何使用Python库PyCINRAD处理中国CINRAD系列天气雷达的基数据,并绘制专业的PPI图像。内容涵盖从环境配置、数据读取、核心绘图到高级定制与批量处理的完整流程,并针对安装依赖、中文乱码、数据范围等常见问题提供了实用的避坑指南,帮助气象工作者高效完成雷达数据可视化。

dog123的博客 221

中望3D 2021 “命令中断”弹窗

在执行的命令如中间计算过程比较长,会弹出“命令中断”窗口,方便用户随时中断当前计算。此效果相当于键盘的Esc键。

因为喜欢,所以坚持。 549

加法器设计—— 原理图与VHDL设计初步

1、在DE2-115开发板上,完成4位全加器系统的设计、下载和功能演示,并在FPGA上实现1位全加器;2、完成3-8译码器的设计、下载和功能演示(利用板上的8段数码管)本次实验在组合逻辑电路的基础上,运用Verilog编程实现了四位全加器和3-8译码器的设计,同时实现了在DE2-115开发板上的下载和功能演示。整个过程加深了我对电路设计和Verilog编程的理解,同时也锻炼了解决问题的能力。

m0_74749526的博客 1234

【GameFramework框架内置模块】6、实体(Entity)

实体Entity就是一个实体的基本单元,类似于Unity的GameObject对象本体,然后这个本体上面附加其他各种各样组件,才能实现各种各样的功能。一般需要在游戏运行时动态加载的游戏对象,比如怪物、武器、子弹、特效,都需要给这个物体挂载一个实体Entity,这样的话就可以方便的对实例出来的对象进行管理。下面就来看一下如何使用吧。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 3136

C++【string类,模拟实现string类】

就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一 不想分享就你争我夺,玩具损坏。可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享。父 母给每个孩子都买一份玩具,各自玩各自的就不会有问题了。

qq_67578580的博客 3697

【推荐100个unity插件之2】 DoTween动画插件的安装和使用整合(最全)

摘要:DOTween动画插件使用指南 DOTween是Unity中强大的动画插件,比原生动画更便捷。安装后需进行初始化设置,通过工具菜单生成程序集。主要提供通用方法(DOTween.To)和便捷方法(如transform.DOMove)两种动画实现方式。插件支持丰富的动画设置(循环、缓动等)和事件回调(OnComplete、OnKill)。还提供动画管理功能,包括清除(DOTween.Clear)、完成(DOTween.CompleteAll)和终止(DOTween.KillAll)动画。常用功能涵盖移动、

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1万+

【C++】string类

C++ string类解析摘要 本文全面解析C++ string类,重点包括: string类解决了C语言字符串的4大痛点:安全性问题、内存管理复杂、功能有限、不符合面向对象思想 string类基础用法和C++11新特性(auto关键字和范围for循环) 详细介绍了5类核心接口: 构造函数(空字符串、C字符串构造等) 容量操作(size()/length()、resize()等) 元素访问和遍历(下标操作、迭代器、范围for) 通过代码示例演示string类的实际应用,包括字符串处理和安全操作 string

凤年徐的博客 3477

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【C++】string类模拟实现:探索其内部机制

string类的模拟实现最主要是实现string类的**构造、拷贝构造、赋值运算符重载**以及**析构函数**,以下是对模拟实现string类变量以及函数的封装,自主实现string类的所有内容

Renswc的博客 3685

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C++ 模拟实现string类

C++—模拟实现string类

Han同学 1941

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【C++】string类的模拟实现

本文围绕 C++ 中 string 类展开。首先介绍了 string 类的模拟实现,包括构造函数、浅拷贝与深拷贝问题,以及拷贝构造和赋值运算符重载的传统与现代写法。现代写法利用临时对象和自动析构特性,提高效率与资源利用率。还介绍了 string 类的其他接口如迭代器和各种操作函数等。接着说明了在 vs 和 g++ 下 string 的结构特点。此外提到了写时拷贝的概念及读取缺陷。最后给出了扩展阅读方向。

2401_82610555的博客 1963

C++中简单自己实现一个string类

工具VS2017 MyString.h #pragma once #include<iostream> using namespace std; class MyString { friend ostream & operator<<(ostream &os, const MyString& s); friend istream & ...

Dxs4396的博客 4274

【C++】模拟实现string类

对string类的模拟实现

dab112的博客 2083

【C++初阶】学习string类的模拟实现

前面已经学习了string类的用法,这篇文章将更深入的学习string类,了解string类的底层是怎么实现的。当然,这里只是模拟一些常用的,不常用的可以看文档学习。

2301_77459845的博客 2764

【C++】string类模拟实现

在之前的两篇博客中已经分享关于string类的使用,有需要可以点击链接看看【C++】string类初步介绍和链接:【C++】string进一步介绍,这次要分享用C++代码来实现string类。

zxctsclrjjjcph的博客 2146

【C++驾轻就熟】string类以及string类的模拟实现

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。 sring类的文档介绍总结:在使用string类时,必须包含#include头文件以及using namespace std; 2. string类对象的容量操作 注意:注意: 上面已经对string类进行了简单的介绍,大家只要能够正常使用即可。在面试中,面试官总喜欢让学

2201_75537851的博客 1182

string类的介绍与使用【C++】

string类是编程语言中用于表示和操作字符串的基本数据类型或类。它提供了一系列方法和操作,允许开发者对字符串进行创建、修改、查找、比较、转换等。string类通常具有不可变性,意味着一旦创建了字符串对象,其内容就不能被修改,但可以创建新的字符串对象来表示修改后的内容。这种特性有助于在多线程环境中保持数据的安全性。string类还提供了各种构造函数、操作符重载和格式化功能,使字符串操作更加灵活和高效。

qq_74013365的博客 3512
上一篇: c++ char_traits模板类的实现!!!
下一篇: Linux shell 遍历文件夹文件和目录的脚本
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值