String.h
#ifndef STRING_H
#define STRING_H
#include <iostream>
#include <memory>
#include <cstring>
class String
{
friend String operator+(const String&, const String&);
friend std::ostream &operator<<(std::ostream&, const String&);
friend bool operator==(const String&, const String&);
friend bool operator!=(const String&, const String&);
friend bool operator<(const String&, const String&);
public:
String() : sz(0), p(nullptr) {}
String(const String &);
String(const char *);
String(size_t, char);
~String() throw();
String& operator=(const String &);
String& operator=(const char *);
String& operator=(char);
String& operator+=(const String &);
String& operator+=(const char *);
char operator[](size_t n) { return *(p + n); }
const char operator[](size_t n) const { return *(p + n); }
String(String &&) throw();
String& operator=(String &&) throw();
const char* begin() { return p; }
const char* begin() const { return p; }
const char* end() { return p + sz; }
const char* end() const { return p + sz; }
size_t size() const { return sz; }
private:
size_t sz;
char *p;
static std::allocator<char> alloc;
};
inline
String::String(const String &s) : sz(s.sz), p(alloc.allocate(sz))
{
// 将s中的内容拷贝到分配好的内存中
std::uninitialized_copy(s.begin(), s.end(), p);
//std::cout << "调用拷贝构造函数" << std::endl;
}
inline
String::String(const char *s)
{
size_t len = strlen(s);
p = alloc.allocate(len);
sz = len;
std::uninitialized_copy(s, s + len, p);
}
inline
String::String(size_t n, char c)
{
p = alloc.allocate(n);
sz = n;
std::uninitialized_fill_n(p, sz, c);
}
inline
String::~String() throw()
{
if(p)
alloc.deallocate(p, sz);
}
inline
String& String::operator=(const String &s)
{
// 分配sz大小的内存
auto newdata = alloc.allocate(s.sz);
// 将s中的内容拷贝到分配好的内存中,首地址为newdata
std::uninitialized_copy(s.begin(), s.end(), newdata);
// 释放原分配的内存
if(p)
alloc.deallocate(p, sz);
// 更新sz和p
sz = s.sz;
p = newdata;
//std::cout << "调用拷贝赋值运算符" << std::endl;
return *this;
}
inline
String& String::operator=(const char *s)
{
if(p)
alloc.deallocate(p, sz);
size_t len = strlen(s);
p = alloc.allocate(len);
std::uninitialized_copy(s, s + len, p);
sz = len;
return *this;
}
inline
String& String::operator=(char c)
{
if(p)
alloc.deallocate(p, sz);
p = alloc.allocate(1);
*p = c;
sz = 1;
return *this;
}
inline
String::String(String &&s) throw() : sz(s.sz), p(s.p)
{
s.sz = 0;
s.p = nullptr;
}
inline
String& String::operator=(String &&s) throw()
{
if(this != &s)
{
if(p) alloc.deallocate(p, sz);
sz = s.sz;
p = s.p;
s.sz = 0;
s.p = nullptr;
}
return *this;
}
#endif
#include "String.h"
// 这一句很关键,因为这样程序才会知道是调用String类中的alloc;否则程序运行时可能找不到alloc
std::allocator<char> String::alloc;
std::ostream &operator<<(std::ostream &os, const String &s)
{
for(auto cp = s.begin(); cp != s.end(); ++cp)
os << *cp;
return os;
}
String operator+(const String &s1, const String &s2)
{
String s;
s.sz = s1.size() + s2.size();
// 分配s1.size()+s2.size()的内存
s.p = String::alloc.allocate(s.sz);
// 将s1和s2的内容拷贝到分配好的内存中
std::uninitialized_copy(s1.begin(), s1.end(), s.p);
std::uninitialized_copy(s2.begin(), s2.end(), s.p + s1.size());
return s;
}
String& String::operator+=(const String &rhs)
{
auto newdata = alloc.allocate(sz + rhs.sz);
std::uninitialized_copy(p, p + sz, newdata);
std::uninitialized_copy(rhs.begin(), rhs.end(), newdata + sz);
if(p) alloc.deallocate(p, sz);
sz += rhs.sz;
p = newdata;
return *this;
}
String& String::operator+=(const char *rhs)
{
size_t rhs_len = strlen(rhs);
auto newdata = alloc.allocate(sz + rhs_len);
std::uninitialized_copy(p, p + sz, newdata);
std::uninitialized_copy(rhs, rhs + rhs_len, newdata + sz);
if(p) alloc.deallocate(p, sz);
sz += rhs_len;
p = newdata;
return *this;
}
bool operator==(const String &s1, const String &s2)
{
if(s1.sz != s2.sz) return false;
size_t sz = s1.sz;
for(size_t i = 0; i < sz; ++i)
{
if(*(s1.p + i) != *(s2.p + i))
return false;
}
return true;
}
bool operator!=(const String &s1, const String &s2)
{
return !(s1 == s2);
}
bool operator<(const String &s1, const String &s2)
{
// 1. 长度不相同,但较短字符串与较长字符串对应的位置相同,则较短字符串<较长字符串
// "Hello" < "Hello World"
// 2. 某些字符对应不一致,则比较第一对相异位置
// "Hello" < "Hiya"
size_t short_size = s1.size();
if(s2.size() < s1.size())
short_size = s2.size();
for(size_t i = 0; i < short_size; ++i)
{
if(*(s1.p + i) < *(s2.p + i))
return true;
else if(*(s1.p + i) > *(s2.p + i))
return false;
}
if(s1.size() < s2.size())
return true;
else
return false;
}
Test.cpp
#include <iostream>
using std::cout; using std::endl;
#include "String.h"
int main()
{
String s1 = "Hello", s2;
s2 = "Hiya";
cout << s1 << endl;
cout << s2 << endl;
if(s1 < s2)
cout << "s1 < s2" << endl;
else if(s1 == s2)
cout << "s1 == s2" << endl;
else
cout << "s1 > s2" << endl;
return 0;
}