用C++实现简单的字符串值类型对象

it2026-08-28  2

问题: 值类型在c++中是一个很重要的概念,指的是一个类的实例像int类型一样,可以被复制、构造、传递,而且不需要用户去担心(至少在表面上)new和delete的问题。 那么构造一个完整的值类型需要注意哪些方面呢?

让我们一字符串类型来做一个简单的设计。

首先我们要明确这个类型的实例可以有哪些操作,我们就要通过构造函数和重载函数实现这些操作。

#include<iostream> #include<cmath> #include<iomanip> #include<vector> using namespace std; struct String { public: String(); String(const char *); String(const String &); String(String &&); ~String(); String & operator=(const String &); String & operator=(String &&); bool operator==(const String &) const; bool operator!=(const String &) const; bool operator<(const String &) const; bool operator<=(const String &) const; bool operator>(const String &) const; bool operator>=(const String &) const; const char *GetBuffer() const; size_t GetLength() const; String operator+(const String &) const; String SubString(int start, int length) const; };

下边是一个简单的字符串值类型实现;

在写这种代码的时候,最好用到单元测试(更大的叫TDD(测试驱动开发,用测试来驱动软件的开发)) 参考书籍 用这种方法的作用:

#include <iostream> #include <cstdlib> #include <cstring> #ifndef _MSC_VER #define strcpy_s(DST,SIZE,SRC) strcpy((DST),(SRC)) #endif #define JSK_ASSERT(EXPRESSION) if(!(EXPRESSION)) throw 0 using namespace std; struct String { private: size_t length; char* buffer; public: String():length{0},buffer{new char[1]{'\0'}} { } String(const char* theBuffer):length{strlen(theBuffer)},buffer{new char[length+1]} { strcpy_s(buffer,length+1,theBuffer); cout << " ="; } String(const String& theString):length{theString.length},buffer{new char[theString.length+1]} { strcpy_s(buffer,length+1,theString.buffer); } String(String&& theString) :length{ theString.length } , buffer{ theString.buffer } { theString.buffer = nullptr; } ~String() { delete[] buffer; } String& operator=(const String& theString) { if (this != &theString) { delete[] buffer; length = theString.length; buffer = new char[length+1]; strcpy_s(buffer,length+1,theString.buffer); } return *this;//这里返回的类型是左值引用类型,并不会在返回时创建零时对象,而且this相对于这个重载函数是一直存在的并不是函数里的局部变量,所以可以返回左值引用类型 } String& operator=(String&& theString) { if (this != &theString) { delete[] buffer; length = theString.length; buffer = theString.buffer; theString.buffer = nullptr; } return *this; } const char* GetBuffer()const { return buffer; } size_t GetLength()const { return length; } }; int main() { { String s;//调用String()默认构造函数 JSK_ASSERT(s.GetBuffer() != nullptr); JSK_ASSERT(s.GetBuffer()[0] == '\0'); JSK_ASSERT(s.GetLength() == 0); } { String s = "This is a string!";//调用 String(const char* theBuffer)初始化(非缺省)构造函数 JSK_ASSERT(s.GetBuffer() != nullptr); JSK_ASSERT(strcmp(s.GetBuffer(), "This is a string!") == 0); JSK_ASSERT(s.GetBuffer()[17] == '\0'); JSK_ASSERT(s.GetLength() == 17); } { String s = "This is a string!"; String t = s;//调用 String(const String& theString)复制构造函数 JSK_ASSERT(t.GetBuffer() != nullptr); JSK_ASSERT(s.GetBuffer() != t.GetBuffer()); JSK_ASSERT(s.GetLength() == t.GetLength()); JSK_ASSERT(strcmp(s.GetBuffer(), t.GetBuffer()) == 0); } { String s = "This is a string!"; s = s;//调用等号运算符重载函数String& operator=(const String& theString) JSK_ASSERT(s.GetBuffer() != nullptr); JSK_ASSERT(strcmp(s.GetBuffer(), "This is a string!") == 0); JSK_ASSERT(s.GetBuffer()[17] == '\0'); JSK_ASSERT(s.GetLength() == 17); } { String s = "This is a string!"; String t; t = s;//调用等号运算符重载函数String& operator=(const String& theString) JSK_ASSERT(t.GetBuffer() != nullptr); JSK_ASSERT(s.GetBuffer() != t.GetBuffer()); JSK_ASSERT(s.GetLength() == t.GetLength()); JSK_ASSERT(strcmp(s.GetBuffer(), t.GetBuffer()) == 0); } { String s = "This is a string!"; String t = std::move(s);//调用String(String&& theString),转移复制构造函数(也即右值引用复制构造函数) JSK_ASSERT(s.GetBuffer() == nullptr); JSK_ASSERT(t.GetBuffer() != nullptr); JSK_ASSERT(t.GetLength() == 17); JSK_ASSERT(strcmp(t.GetBuffer(), "This is a string!") == 0); } { String s = "This is a string!"; s = std::move(s); JSK_ASSERT(s.GetBuffer() != nullptr); JSK_ASSERT(strcmp(s.GetBuffer(), "This is a string!") == 0); JSK_ASSERT(s.GetBuffer()[17] == '\0'); JSK_ASSERT(s.GetLength() == 17); } { String s = "This is a string!"; String t; t = std::move(s);//调用转移操作符重载函数String& operator=(String&& theString)(也即右值引用操作符重载函数) JSK_ASSERT(s.GetBuffer() == nullptr); JSK_ASSERT(t.GetBuffer() != nullptr); JSK_ASSERT(t.GetLength() == 17); JSK_ASSERT(strcmp(t.GetBuffer(), "This is a string!") == 0); } return 0; }
最新回复(0)