string实现

目标:

1.string接口纯虚函数类StringInterface;

2.我的ubuntu上string实现重写(但不包括写时复制);

3.一种支持小字符串优化的实现;

4.基于StringInterface的多态测试case集合;

6.多场景性能分析。

当前时间不太够,只差不多完成了1\2,先放到博客备忘,之后补上。


string_interface.h

//#define MYCODE_TEST_MODE 1
#ifndef MYCODE_STRING_INTERFACE_H
#include <cstddef>
namespace mycode{
//缺点:用全部纯虚的interface不是好事,造成了string的各种实现的对应函数也是虚的,而实际上string的各种实现不应该有子类了,所以对于string指针或引用的函数调用运行时查虚函数表是不必要的浪费。
//优点:用interface可以使得接口统一且没有遗漏,并且通过多态进行测试也比较方便
//实现可以不继承全部接口,也可以继承,可以用一个定义开关MYCODE_TEST_MODE控制
//限定符,最好都加,1.简单的文档;2.防止错误的调用;3.编译器可能的优化;4.库可能的优化;5.编译器警告。这些里面1最重要。
//线程安全不考虑,异常安全按注释,提供基本及以上保证。
class StringInterface{
	public:
		static const size_t nopos = (size_t)-1;
//迭代器,假设实现全是用连续内存实现的,这样"迭代器"生成比较方便,因为迭代器兼容指针并且当作最高级的迭代器(random)	
//“长度类”接口
//位置相关函数
//操作相关
//操作符重载
//std::swap也需要加特化版本
//改变类
//析构函数
//此外,拷贝构造函数、右值拷贝构造函数,左右值赋值操作符;友元函数的输入输出也应该实现;这些貌似没法纯虚了。
//除了这个VIRTUAL StringInterface substr(size_t pos,size_t len) const noexcept(false) PUREVIRTUAL;其他还是能实现。	
#define MYCODE_STRING_INTERFACE	\
		VIRTUAL char *begin() noexcept PUREVIRTUAL;	\
		VIRTUAL char *end() noexcept PUREVIRTUAL;	\
		VIRTUAL const char *cbegin() const noexcept PUREVIRTUAL;	\
		VIRTUAL const char *cend() const noexcept PUREVIRTUAL;	\
	\
		VIRTUAL size_t size() const noexcept PUREVIRTUAL;	\
		VIRTUAL size_t capacity() const noexcept PUREVIRTUAL;	\
		VIRTUAL void resize(size_t) noexcept(false) PUREVIRTUAL;	\
		VIRTUAL bool empty() const noexcept PUREVIRTUAL;	\
		VIRTUAL void reserve(size_t) noexcept(false) PUREVIRTUAL;	\
		VIRTUAL void shrink_to_fit() noexcept(false) PUREVIRTUAL;	\
	\
		VIRTUAL char &operator[](size_t pos) noexcept(false) PUREVIRTUAL;	\
		VIRTUAL const char &operator[](size_t pos) const noexcept(false) PUREVIRTUAL;	\
		VIRTUAL char &back() noexcept(false) PUREVIRTUAL;	\
		VIRTUAL const char &back() const noexcept(false) PUREVIRTUAL;	\
	\
		VIRTUAL size_t find_first_of(char c) const noexcept PUREVIRTUAL;	\
		VIRTUAL const char *c_str() const noexcept PUREVIRTUAL;	\
		VIRTUAL int compare(const StringInterface &si) const noexcept PUREVIRTUAL;	\
		VIRTUAL size_t find(const StringInterface &si) const noexcept PUREVIRTUAL;	\
	\
		VIRTUAL bool operator==(const StringInterface &lhs) const noexcept PUREVIRTUAL;	\
		VIRTUAL bool operator<(const StringInterface &lhs) const noexcept PUREVIRTUAL;	\
		VIRTUAL bool operator>(const StringInterface &lhs) const noexcept PUREVIRTUAL;	\
		VIRTUAL bool operator!=(const StringInterface &lhs) const noexcept PUREVIRTUAL;	\
		VIRTUAL void swap(StringInterface &lhs) noexcept PUREVIRTUAL;	\
	\
		VIRTUAL void push_back(char c) noexcept(false) PUREVIRTUAL;	\
		VIRTUAL void pop_back() noexcept PUREVIRTUAL;	\
		VIRTUAL void insert(size_t pos,char c) noexcept(false) PUREVIRTUAL;	\
		VIRTUAL void erase(size_t pos) noexcept(false) PUREVIRTUAL;	
#ifdef MYCODE_TEST_MODE
#define VIRTUAL virtual
#define PUREVIRTUAL = 0 
	public:
		MYCODE_STRING_INTERFACE
		VIRTUAL ~StringInterface() noexcept {};	
#undef VIRTUAL
#undef PUREVIRTUAL 
#endif
#define VIRTUAL
#define PUREVIRTUAL 
};

}
#define MYCODE_STRING_INTERFACE_H
#endif

ubuntu_string.h

#include <iostream> 
#include <stdexcept>
#include "string_interface.h"
namespace mycode{
	//我的ubuntu上的string类似实现
	//不支持小string优化,string占用最小栈空间和写时复制
	class UbuntuString : public StringInterface{
		public:
			UbuntuString() noexcept = default;
			UbuntuString(const UbuntuString &us) noexcept(false);
			UbuntuString(const char *,size_t) noexcept(false);
			//按effective c++说法,这个noexcept很重要
			UbuntuString(UbuntuString &&us) noexcept;
			UbuntuString &operator=(const UbuntuString &lhs);
			UbuntuString &operator=(UbuntuString &&lhs) noexcept;
			~UbuntuString() noexcept;

			//头文件慎用命名空间,cpp文件无所谓
			friend std::istream& operator<<(UbuntuString &us,std::istream &is);
			friend std::ostream& operator<<(std::ostream &os,const UbuntuString &us);

			//公共接口
			MYCODE_STRING_INTERFACE
			UbuntuString substr(size_t pos,size_t len) const noexcept(false);
		private:
			char *_ps = NULL;
	};
}


ubuntu_string.cpp

#include "ubuntu_string.h"
#include <cstddef>
#include <cstring>

//暂不实现写时复制
namespace mycode{
	typedef struct{
		size_t len;
		size_t max;
		size_t refCount;
	} StringHeader;

	//没有判断ps==NULL,由调用时保证
	static inline StringHeader *getSH(const char *ps) noexcept {
		return reinterpret_cast<StringHeader *>(reinterpret_cast<StringHeader *>(const_cast<char *>(ps)) - 1);
	}

	static char *newSH(const char *ps,size_t size) noexcept(false) {
		char *nps = new char[size + sizeof(StringHeader) + 1];	//new失败的异常直接抛bad_allocate到外界,期望调用者能根据接口noexcept指示符自行处理,+1是要兼容c风格字符串,即c_str的返回
		StringHeader *psh = getSH(nps);
		psh->max = size;
		psh->refCount = 1;
		if(ps == NULL || size == 0)
			psh->len = 0;
		else{
			int len = (size > getSH(ps)->len)?getSH(ps)->len:size;
			memcpy(nps,ps,len);
			*(nps + len + 1) = 0;
			psh->len = len;
		}
		return nps;
	}

	//只增不减,除了isShrink时(一般不会调用)
	static char *resizeSH(char *ps,size_t size,bool isShrink = false) noexcept(false) {
		char *nps;
		if(ps == NULL || getSH(ps)->max < size || isShrink){
			nps = newSH(ps,size);
			if(ps != NULL)
				delete [] ps;
			ps = nps;
		}
		if(getSH(ps)->len > size){
			getSH(ps)->len = size;
			ps[size] = 0;
		}
	}

	//同下都是inline的好材料,但是为了隐藏实现细节还是选择放cpp里面了,不过貌似可以本编译单元inline
	inline size_t UbuntuString::size() const noexcept {
		if(_ps == NULL)
			return 0;
		return getSH(_ps)->len;
	}

	inline size_t UbuntuString::capacity() const noexcept {
		if(_ps == NULL)
			return 0;
		return getSH(_ps)->max;
	}

	void UbuntuString::reserve(size_t size) noexcept(false) {
		_ps = resizeSH(_ps,size);
	}

	void UbuntuString::resize(size_t size) noexcept(false) {
		if(_ps == NULL || getSH(_ps)->len < size)
			return;
		getSH(_ps)->len = size;
		_ps[size] = 0;
	}

	inline bool UbuntuString::empty() const noexcept {
		return size() == 0;
	}

	void UbuntuString::shrink_to_fit() noexcept(false) {
		if(empty())
			return;
		_ps = resizeSH(_ps,size(),true);
	}

	const char *UbuntuString::cbegin() const noexcept {
		if(empty())
			return NULL;
		return _ps;
	}

	const char *UbuntuString::cend() const noexcept {
		if(empty())
			return NULL;
		return _ps + size();
	}

	//用const版本实现非const版本,effective c++推荐
	char *UbuntuString::begin() noexcept {
		return const_cast<char *>(cbegin());
	}

	char *UbuntuString::end() noexcept {
		return const_cast<char *>(cend());
	}

	const char &UbuntuString::operator[](size_t pos) const noexcept(false) {
		if(pos >= size())
			throw std::out_of_range("pos is not valid");
		return _ps[pos - 1];
	}

	char &UbuntuString::operator[](size_t pos) noexcept(false) {
		return const_cast<char &>((static_cast<const UbuntuString *>(this))->operator[](pos));
	}

	const char &UbuntuString::back() const noexcept(false) {
		if(size() == 0)
			throw std::out_of_range("string is empty");
		return _ps[size() - 1];
	}

	char &UbuntuString::back() noexcept(false) {
		return const_cast<char &>((static_cast<const UbuntuString *>(this))->back());
	}

	size_t UbuntuString::find_first_of(char c) const noexcept {
		if(empty())
			return nopos;
		//可以用strchr,这里还是自己实现
		char *ptemp = _ps;
		while(*ptemp != 0 && *ptemp != c)
			ptemp++;
		if(*ptemp)
			return ptemp - _ps;
		return nopos;
	}

	UbuntuString::UbuntuString(const char *ps,size_t size) noexcept(false) {
		if(ps == NULL || *ps == 0)
			_ps = 0;
		_ps = newSH(ps,size);
	}

	const char *UbuntuString::c_str() const noexcept {
		return _ps;
	}

	UbuntuString UbuntuString::substr(size_t pos,size_t len) const noexcept(false) {
		if(len == 0 || pos >= size() )
			return UbuntuString();
		return UbuntuString(_ps + pos,(len > (size() - pos))?(size() - pos):len);
	}

	//可以和任意支持c_str的StringInterface的实现比较
	int UbuntuString::compare(const StringInterface &si) const noexcept {
		return strcmp(_ps,si.c_str();
	}

	UbuntuString::UbuntuString(const UbuntuString &us) noexcept(false) {
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值