1——自我实现一个简洁版的String类

在C++中有C没有的string字符串类型,string类型的数据其实是一个指向字符串首地址的指针变量,因此在string类的默认成员函数拷贝构造和赋值运算符的重载就会涉及到深浅拷贝的问题,一不小心要么就是内存泄露要么就是多次释放同一块空间导致程序崩溃,下面就来模拟实现一个简洁版的String类:

既然是指向一个字符串的指针,因此类的成员变量就需要有一个char*类型的指针;

#include <iostream>
#include <string.h>
using namespace std;

class CMyString
{
public:
    CMyString(const char* str);
    CMyString(const CMyString& s); 
    CMyString& operator=(CMyString s); 
    //CMyString& operator=(const CMyString& s);
    ~CMyString();

    void print_string();

private:
    char* _str;
};

上面为简单的CMyString类的声明,接下来要实现最主要的四个默认的成员函数:

构造函数主要是为成员变量_str分配内存空间并且初始化为形参的值;

CMyString::CMyString(const char* str)   //含参的构造函数
    :_str(NULL)
{
        assert(str);
    _str = new char[_capacity];
    strcpy(_str, str);
}
CMyString::CMyString()    //默认的构造函数
        :_str(NULL)
    {}

拷贝构造就会涉及到了深浅拷贝的问题,因为不能使两个字符串的指针指向同一块地址空间:

CMyString::CMyString(const CMyString& s)
        :_str(NULL)
{
        CMyString tmp(s._str);//用前面实现的构造函数构造出一个值为s._str的临时类对象
    swap(_str, tmp._str);//交换临时类的字符串和_str,这样当tmp出了作用域就会自动释放
}

赋值运算符的重载函数同样会涉及到深浅拷贝的问题:

//这是一种比较现代的写法,没有用引用s就为一个临时的类对象,出了作用域就会自动调用析构函数
CMyString& CMyString::operator=(CMyString s)
{
    if(strcmp(s._str, _str) != 0)
        swap(_str, s._str);//交换二者的值就能将有效值赋给_str,而原来的值随s释放
    return *this;
}

//较为传统的写法,先要判断是否自己给自己赋值再释放自己空间,重新开辟一块空间拷贝所需值
//CMyString& CMyString::operator=(const CMyString& s)
//{
//  if(this != &s)
//  {
//      delete[] _str;
//      _str = new char[strlen(s.str)+1];
//      strcpy(_str, s._str);
//  }
//  return *this;
//}

但是在上面注释掉的一种写法中存在一个问题,就是如果将自己本身的地址空间释放掉了之后,再去new一块空间有可能会new不出来,这样的话不仅不能成功赋值,连自身本就存在的值也丢掉了,因此可以优化为如下代码:

CMyString& CMyString::operator=(const CMyString& s)
{
    if(this != &s)
    {
        char *tmp = new char[strlen(s.str)+1];
        if(tmp != NULL)
        {
            delete[] _str;
            _str = tmp;
            strcpy(_str, s.str);
        }
    }
    return *this;
}

析构函数是在当类对象出了所在作用域时自动调用完成清理工作的:

CMyString::~CMyString()
{
    if(_str != NULL)       //检查类成员是否为空,delete不能释放空指针
    {   
        delete[] _str;
        _str = NULL;       //防止出现野指针
    }   
}

最后一个print_string函数是为了打印验证结果,这里就不写了;

main函数:

int main()
{
    CMyString s1("this is my string...");
    s1.print_string();
    CMyString s2("hello world...");
    s2.print_string();
    CMyString s3(s2);
    s3.print_string();
    s3 = s1;
    s3.print_string();

    return 0;
}

运行程序结果如下:

《完》

时间: 2024-12-20 13:20:46

1——自我实现一个简洁版的String类的相关文章

实现一个简洁版的String类

浅拷贝: 深拷贝: 注意事项:在浅拷贝中复制构造必须构造一个匿名对象在进行交换,在赋值操作符中传参时不能使用引用.

实现以一个简洁版的string类

浅拷贝: 分析:如果在赋值运算时不使用引用会造成程序崩溃,在调用复制构造时是s1的_str会出现一个随机值,本来应该是被析构过的应为空,所以在测试时出了作用域再去析构时就会出现错误.

实现简洁版的string类

#include<iostream> using namespce std; class String { public: String() :_str(new char[1]) { _str='\0'; } String(const char* str)//一个字符串的拷贝 :_str(new char[strlen(str)+1] { strcpy(_str,str); } String (const String&str)//一个对象的拷贝 :_str(NULL) { Strin

【C++】实现一个简洁版的class String

//实现一个简洁版的class String #include <iostream> #include <string.h> using namespace std; class String { public: String() { _str = new char[1]; _str[0] = '\0'; } String(const char *str) { _str = new char[strlen(str) + 1]; strcpy(_str, str); } String

一个简单实现的string类

为了复习c++知识,简单的实现一个string类,类名为CMyString 环境说明:windows 7 64位 开发工具:Visual Studio 2015 CMyString类的头文件CMyString.h 1 #include <iostream> 2 3 #ifndef __C_MY_STRING__ 4 #define __C_MY_STRING__ 5 6 class CMyString 7 { 8 public: 9 //默认构造函数 10 CMyString(); 11 //

造轮子:新建一个属于自己的String类

练习造轮子,新建一个属于自己的MyString类 首先来开启检测内存泄漏的函数 在main里添加 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); 开启内存泄漏检测 int main() { _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); int *p = new int; return

码农的视角:马云菜鸟物流的一个简洁版实现

龟兔赛跑的物流玄机 80后的我们大都接受了一个励志的寓言故事:龟兔赛跑.这个寓言有很多版本,有的说兔子太骄傲,在比赛的时候睡大觉,结果被乌龟给拼命地赢了.有的说,乌龟很聪明,在比赛的路上不满了同伴,每个同伴看到兔子来,就开始跑,结果乌龟聪明地赢了兔子. 龟兔赛跑的第二个版本,充满了物流玄机:假如一个用户在XX地方买了一个商品,那什么样才能更快地把商品送到该用户手中.用龟兔聪明的版本,就是在离用户近的地方,先合理准备着该商品. 其实这个从技术的角度来看可以说是CACHE,或者说CDN,其架构图如下

实现一个简洁版的智能指针

//智能指针可以自动销毁,用引用计数技术实现 #include<iostream> using namespace std; template<class T> class SmartPtr { protected:                  T* _ptr;                  size_t* _cout;                  void clear()                 {                             

自己动手写Java String类

很早想造个轮子了,听说不想造轮子的程序员不是好程序员,用惯了Apache的众多开源项目,却没看过开源一句代码.最近看了几篇卖焦虑的文章之后,突然变得慌张起来,于是在百忙之中难得一点闲第一次打开了JDK的源码包.初读:晦涩难懂,3千多行代码,全英文注释,有一些陌生的语法和调用陌生的类足矣吓退一个中年程序员.再度:只读个轮廓,这String.class也就是注释写的全写得多,核心代码不多嘛!三读:哇喔,整个String类核心变量就一个char[]数组嘛: private final char val