【C++】string

版权声明:本文为博主原创文章,未经博主允许不得转载。Copyright (c) 2018, code farmer from sust. All rights reserved. https://blog.csdn.net/sustzc/article/details/82734872

    if (_str)
    {
        _str = new char[1];
        *_str = '\0';
    }
    
        | |
        v v
    
    if (_str)
    {
        _str = "";
    }
    
    ~String()
    {
        if(_pStr)
            delete[] _pStr;
    }
    
实现string类反例:浅拷贝  (共享空间,销毁时free多次)  eg:拷贝美人鱼的上半身
    eg: String s1("hello");
        String s2(s1);
        String s3 = s1;
        默认拷贝构造函数使用的是浅拷贝。
解决方法:深拷贝(创建一个新的空间)  eg:拷贝美人鱼不为人知的下半身    

    String(const String& s)
    :_str(new char[strlen(s._str) + 1])
    {
        strcpy(_str, s._str);
    }
    
注意点:赋值运算符的重载,考虑当前this对象和创建对象的地址是否一致.
(先释放_str空间,再重新开辟和_str同样大小的空间,最后strcpy)
    
    // 有问题,如果没有申请到新的空间,然而之前的空间已经被释放掉了。
    String& operator=(const String& s)
    {
        if (this != &s)
        {
            delete[] _str;
            _str = new char[strlen(s._str) + 1];
            strcpy(_str, s._str);
        }
        
        return *this;
    }
    
    // 解决方法:先申请空间,然后拷贝完成后再去释放,类似于单链表的任意结点插入。
    String& operator=(const String& s)
    {
        if (this != &s)
        {
            char *pStr = new char[strlen(s._str) + 1];
            strcpy(pStr, s._str);
            delete[] _str;
            _str = pStr;
        }
        
        return *this;
    }
    
现代写法
    // 拷贝构造
    String(const String& str)
    :_str(NULL)
    {
        String tmpStr(str._str);
        swap(_str,tmpStr._str);
    }
    // 赋值重载
    String& operator= (const String& str)
    {
        if (this != &str)
        {
            String tmpStr(str._str);
            swap(_str,tmpStr._str);
        }
        
        return *this;
    }
    
    // 相当于在传值的时候就创建了一个临时对象
    String& operator= (String str)
    {
         swap(_str,str._str);
         return *this;
    }
    
写时拷贝
    String(const char* str = "")
    {
        _str = new char[strlen(str) + 1];
        strcpy(_str, str);
        _pcount = new int(1);
    }
    
    String(const String& s)
    {
        _str = s._str;
        _pcount = s._pcount;
        ++(*_pcount);
    }
    
    String& operator=(const String& s)
    {
        if (_str != s._str)
        {
            if (--(*_pcount) == 0)
            {
                delete[] _str;
                delete _pcount;
            }
            
            _str = s._str;
            _pcount = s._pcount;
            ++(*_pcount);
        }
        
        return *this;
    }
    
    ~String()
    {
        if (--(*_pcount) == 0)
        {
            delete[] _str;
            delete _pcount;
        }
    }
    
    private:
        char* _str;
        int *_pcount;
    
    
如果一个类中涉及了资源的管理,就需要考虑深浅拷贝的问题。
    引起原因:没有显示提供拷贝构造函数或者赋值运算符重载
        编译器会合成一个默认的   浅拷贝
    什么是浅拷贝?
        位的拷贝->内存拷贝     多个对象共用一份资源,一份资源被销毁多次会造成程序崩溃。
    
    什么是深拷贝?
        传统写法
        现代写法
    
string类    
#include <string>
    
    string str1("1234567890");  // "1234567890"
    string str2;  // ""
    string str3(str1, 3, 3);  // "456"
    string str4(str1, 3);  // "4567890"  如果第三个参数没有给出,那就表示从下标为3的位置开始,直到字符串结束。
    
    size length都是求长度  resize更改size  reserve更改capacity
    连续空间,所以支持operator[],随机访问。  at也可以
    append拼接  assign赋值  c_str使用C格式的字符串  find正向查找  rfind反向查找
    string::iterator是一种类型   与指针类似
        string::iterator it = str1.begin();
        while (it != str1.end())
        {
            cout<<*it<<" ";
            ++it;
        }
    默认capacity是15
    ListNode(const DataType& data = DataType())  缺省值:如果是内置类型,那么值为0,如果是自定义类型,那么调用构造函数。
    list不能直接使用++,因为不是连续空间。
        
    string类大小是32字节。
    
vector list map

const DataType& Front()const    // 存在const对象的const类型的变量

猜你喜欢

转载自blog.csdn.net/sustzc/article/details/82734872
今日推荐