Свой быстрый класс string, вопросы по оптимизации скорости
Создал свой класс string. Цель создания своего класса строк - это скорость работы со строками и второе в образовательных целях. Если реализация получится удачной сделаю библиотеку для личного использования. new и delete решил не использовать, так как использую простой тип char.Прошу просмотреть код и дать рекомендации по оптимизации. Исправлю уже данные замечания и выложу повторно. За ранее благодарю за ответы.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <malloc.h>
namespace str
{
struct string
{
private:
#pragma region ========================== Variable ==============================
typedef struct
{
char *p_str;
size_t length;
}stringA;
stringA str{};
const type_info& ti_c = typeid(const_cast<const char * >(str.p_str));
#pragma endregion
#pragma region ========================== Private Function ==============================
_inline void clr()
{
if(str.p_str) free(str.p_str);
str.p_str = nullptr; str.length = 0U;
}
//------------------------------------------------------------------
_inline bool __type_c(const type_info& ti){return ti_c == ti;}
#pragma endregion
public:
#pragma region ==================================== Constructor ======================================
/* Конструктор однобайтовые символы */
string(const char *p_str)
{
clr();
// if(p_str){
if((str.length = strnlen_s(p_str, SIZE_MAX) ) > 0U)
{
if(str.p_str = static_cast<char *>(malloc(sizeof(char) * (str.length + 1) ) ) )
{
strncpy_s(str.p_str, str.length + 1, p_str, _TRUNCATE);
str.p_str[str.length] = '\0';
}
}else{ str.p_str = static_cast<char *> (calloc(1, sizeof(char) ) );}
// }
}
//------------------------------------------------------------------
/* Конструктор по умолчанию */
explicit string(){
clr();
str.p_str = static_cast<char *> (calloc(1, sizeof(char) ) );
}
//------------------------------------------------------------------
/* Конструктор копирования */
string(const string& s)
{
// if(s.c_str() == ""){ str.p_str = static_cast<char *> (calloc(1, sizeof(char) ) );}else{
clr();
if ((str.length = strnlen_s(s.c_str(), SIZE_MAX)) > 0U) {
if ((str.p_str = static_cast<char *> (malloc(sizeof(char) * (str.length + 1) ) ) ) != nullptr) {
strncpy_s(str.p_str, str.length + 1, s.c_str(), _TRUNCATE);
str.p_str[str.length] = '\0';
}
}
//}
}
//------------------------------------------------------------------
/* Конструктор перемещения */
string(string &&moved) noexcept // ссылка rvalue
{
str.p_str = moved.str.p_str;
str.length = moved.str.length;
moved.str.p_str = nullptr;
// if(str.p_str == nullptr){ str.p_str = static_cast<char *> (calloc(1, sizeof(char) ) ); str.length=0U;}
}
//------------------------------------------------------------------
~string(){ clr(); }
#pragma endregion
#pragma region ====================================== Class Members =======================================
//------------------------------------------------------------------
_inline size_t length() const { return str.length ; }
//------------------------------------------------------------------
_inline size_t string_size() const {
return (str.p_str == nullptr) ? 0U : ((str.length + 1) * sizeof(char));
}
//------------------------------------------------------------------
/* Добавляем строку с реолакацией памяти */
void add(const char *p_str_in)
{
size_t l = 0U;
// if(str.p_str == nullptr) return;
if ((l = strnlen_s(p_str_in, SIZE_MAX)) != 0U) {
if ((str.p_str = static_cast<char *> (realloc(str.p_str, (str.length + l + 1) * sizeof(char) ) ) ) != nullptr) {
if(!strcat_s(str.p_str, str.length + l + 1, p_str_in)) str.length += l;
str.p_str[str.length] = '\0';
}//else{ str.p_str = static_cast<char *> (calloc(1, sizeof(char) ) ); str.length=0U;}
}
}
//------------------------------------------------------------------
_inline const char* c_str() const {
return ((str.p_str != nullptr) ? str.p_str : const_cast< char * >(""));
}
//------------------------------------------------------------------
/* Вывести символ в строке по индексу от нуля до str.length - 1 */
_inline char ch_at(size_t index) const {
return (/*(str.p_str != nullptr) && */(index < str.length)) ? str.p_str[index] : '\0';
}
//------------------------------------------------------------------
/* Заменить символ встроке по индексу от нуля до str.length - 1 */
_inline void ch_set_at(size_t index, char ch) {
if(/*(str.p_str != nullptr) && */(index < str.length)) str.p_str[index] = ch;
}
//------------------------------------------------------------------
_inline void clear(){ str.p_str = static_cast<char *> (calloc(1, sizeof(char) ) ); str.length = 0U;}
#pragma endregion
#pragma region ====================================== Operator Reload ============================================
//------------------------------------------------------------------
string& operator +=(string const &s ) {
this->add(const_cast<char *>(s.c_str()));
return *this;
}
//------------------------------------------------------------------
string& operator +=(char *s ) {
this->add(static_cast<char *>(s));
return *this;
}
//------------------------------------------------------------------
const auto& operator = (const string& s)
{
// if (s.c_str() == "")return this;
clr();
if ((str.length = strnlen_s(s.c_str(), SIZE_MAX)) != 0U) {
if ((str.p_str = static_cast<char *>(malloc(sizeof(char) * (str.length + 1) ) ) ) != nullptr) {
strncpy_s(str.p_str, str.length + 1, s.c_str(), _TRUNCATE);
str.p_str[str.length] = '\0';
}
}
return this;
}
#pragma endregion
//------------------------------------------------------------------
friend std::ostream &operator <<(std::ostream &ostr, string const &point) { ostr << point.c_str(); return ostr; }
/* Конец string */
};
//------------------------------------------------------------------
const string operator + (const string &L, const string &R){ return string(L) += R;}
/* Конец области str:: */
};
//===============================================================================================================================
Вот самая последняя версия класса с нетерпением жду рекомендаций.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <malloc.h>
#include <cassert>
namespace str
{
#ifndef SIZE
constexpr size_t SIZE_STRING = 260 ; /* символов */
#else
constexpr size_t SIZE_STRING = SIZE ;
#if (SIZE < 260)
constexpr bool STACK_STRING = true ; /* Возможно для маленьких строк сделаю на стеке */
#else
constexpr bool STACK_STRING = false ;
#endif
#endif
class string
{
//------------------------------------------------------------------
private:
size_t leng; /* Количество символов в строке */
size_t size_str; /* Размер выделенной памяти для строки */
char *p_str; /* Строка */
//------------------------------------------------------------------
void clr()
{
if(p_str != nullptr) free(p_str);
p_str = nullptr; size_str = leng = 0U;
}
//------------------------------------------------------------------
auto realloc_foo(size_t &len)
{
char *p_str_t = nullptr;
if (len == leng)return p_str;
/* Где то тут проверка будет нужно пере выделять или нет */
if ((p_str_t = static_cast<char *> (realloc(p_str, (leng + len + 1) * sizeof(char)))) != nullptr) {
p_str = p_str_t; p_str_t = nullptr;
}else{ /* Что делать в этом месте в случае неудачи? */ }
return p_str;
}
//------------------------------------------------------------------
auto malloc_foo(size_t &len)
{
/* Тут будет реализация буфера size_str от SIZE_STRING,
чтобы избежать лишнего выделения, если len > size_str и SIZE_STRING выделяем len в противном либо SIZE_STRING либо оставляем без изменений */
char *p_str_t = nullptr;
if ((p_str_t = static_cast<char *>(malloc(sizeof(char) * (len + 1) ) ) ) != nullptr) {
p_str = p_str_t; p_str_t = nullptr;
}else{ /* Что делать в этом месте в случае неудачи? */ }
return p_str;
}
//------------------------------------------------------------------
void construct(const char *pstr) {
assert(pstr != nullptr);
if((leng = strnlen_s(pstr, SIZE_MAX) ) > 0U) {
strncpy_s(malloc_foo(leng), leng + 1, pstr, _TRUNCATE);
}
}
//------------------------------------------------------------------
public:
/* Конструктор однобайтовые символы */
string(const char *pstr) : leng(0U), size_str(0U), p_str(nullptr) { construct(pstr); }
//------------------------------------------------------------------
/* Конструктор по умолчанию */
string() : leng(0U), size_str(0U), p_str(nullptr) {
p_str = static_cast<char *> (calloc(SIZE_STRING, sizeof(char) ) );
}
//------------------------------------------------------------------
/* Конструктор копирования */
string(const string& s) { construct(s.c_str()); }
//------------------------------------------------------------------
/* Конструктор перемещения */
string(string &&moved) noexcept : leng(0U), size_str(0U), p_str(nullptr) // ссылка rvalue
{
clr();
p_str = moved.p_str;
leng = moved.leng;
moved.p_str = nullptr;
moved.leng = 0U;
}
//------------------------------------------------------------------
~string(){ clr(); }
//------------------------------------------------------------------
size_t length() const { return leng ; }
//------------------------------------------------------------------
size_t string_size() const {
return (p_str == nullptr) ? 0U : ((leng + 1) * sizeof(char));
}
//------------------------------------------------------------------
/* Добавляем строку с реоллакацией памяти */
void add(const char *p_str_in)
{
size_t l = 0U;
assert(p_str_in != nullptr);
//if(p_str == nullptr) return;
if ((l = strnlen_s(p_str_in, SIZE_MAX)) != 0U) {
if(!strcat_s(realloc_foo(l), leng + l + 1, p_str_in)) leng += l;
p_str[leng] = '\0';
}
}
//------------------------------------------------------------------
const char* c_str() const {
return ((p_str != nullptr) ? p_str : const_cast< char * >(""));
}
//------------------------------------------------------------------
/* Вывести символ в строке по индексу от нуля до str.length - 1 */
char ch_at(size_t index) const {
return ((p_str != nullptr) && (index < leng)) ? p_str[index] : '\0';
}
//------------------------------------------------------------------
/* Заменить символ встроке по индексу от нуля до str.length - 1 */
void ch_set_at(size_t index, char ch) {
if((p_str != nullptr) && (index < leng)) p_str[index] = ch;
}
//------------------------------------------------------------------
void clear(){ p_str = static_cast<char *> (calloc(SIZE_STRING, sizeof(char) ) ); leng = 0U;}
//------------------------------------------------------------------
string& operator +=(string const &s ) {
this->add(const_cast<char *>(s.c_str()));
return *this;
}
//------------------------------------------------------------------
string& operator +=(const char *s ) {
this->add(const_cast<char *>(s));
return *this;
}
//------------------------------------------------------------------
auto & operator = (const string & s) {
string tmp(s); swap (*this, tmp);
return *this;
}
//------------------------------------------------------------------
auto& operator=(string&& moved) noexcept {
swap (*this, moved); return *this;
}
//------------------------------------------------------------------
auto& operator[] (const size_t index){ assert(index < leng); return p_str[index]; }
const auto& operator[] (const size_t index) const{assert(index < leng); return p_str[index]; }
//------------------------------------------------------------------
friend std::ostream &operator <<(std::ostream &ostr, string const &point) { ostr << point.c_str(); return ostr; }
friend void swap (string &l, string &r)
{
std::swap (l.p_str , r.p_str);
std::swap (l.leng , r.leng);
std::swap (l.size_str , r.size_str);
}
friend bool operator < (const string& l, const string& r)noexcept
{
// реализация
}
friend bool operator == (const string& l, const string& r)noexcept
{
//реализация
}
/* Конец string */
};
//------------------------------------------------------------------
inline const string operator + (const string &L, const string &R){ return string(L) += R;}
/* Конец области str:: */
};
//=