栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

写时拷贝/写时复制技术

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

写时拷贝/写时复制技术

拷贝控制

C++提供两个拷贝控制函数

  • 拷贝构造函数
  • 拷贝赋值运算符重载

例如:String类

class String{
public:
        String(const char* str = NULL);
        String(const String& str);
        String& operator=(const String& str);
        ~String();
        size_t size()const;
        friend ostream& operator<<(ostream& os,String const& str);
private:
        char* data;
};

C++11增加了移动构造函数和移动赋值运算符重载。

深拷贝与浅拷贝 概念
  • 浅拷贝:只拷贝指针地址。
    通常默认拷贝构造函数与赋值运算符重载都是浅拷贝。

  • 深拷贝:重现分配堆内存,拷贝指针指向内容。

例如:String类

String::String(const char* str){
        if(NULL == str){
                data = new char[1];
                data[0] = '';
        }else{
                data = new char[strlen(str)+1];
                strcpy(data,str);
        }

}
String::~String(){
        delete [] data;
        data = NULL;
}
String::String(const String& str){
        data = new char[str.size()+1];
        strcpy(data,str.data);
}
String& String::operator=(const String& str){
        if(this != &str){
                delete [] data;
                data = new char[str.size()+1];
                strcpy(data,str.data);
        }
        return *this;
}
inline size_t String::size()const{
        return strlen(data);
}

ostream& operator<<(ostream& os,const String& str){
        return os << static_cast(str.data) << ':' << str.data;
}

测试代码

int main(){
        String s1("Hello World");
        String s2 = s1;
        String s3;
        s3 = s1;
        cout << s1 << endl;
        cout << s2 << endl;
        cout << s3 << endl;
}
比较

优点缺点
浅拷贝只有一份数据,节省空间。因为多个指针指向同一个空间,容易引发同一内存多次释放的问题。
深拷贝每个指针指向不同地址,没有同一内存多次释放的问题。存在多份相同数据,浪费空间。

浅拷贝与深拷贝的优缺点分别互为彼此的优缺点。有什么办法可以兼有二者的优点?

主要解决问题:

  1. 数据相同时只有一份内存。
  2. 不会出现多次释放问题。
计数器技术:数据相同共享一份内存

计数器技术就是兼有浅拷贝与深拷贝优点的一种技术。

在类声明中添加了计数器s_count。

class String{
public:
        String(const char* str = NULL);
        String(const String& str);
        String& operator=(const String& str);
        ~String();
        size_t size()const;
        friend ostream& operator<<(ostream& os,String const& str);
private:
        char* data;
        static int s_count;
};

实现中增加计数处理

int String::s_count = 0;
String::String(const char* str){
        if(NULL == str){
                data = new char[1];
                data[0] = '';
        }else{
                data = new char[strlen(str)+1];
                strcpy(data,str);
        }
        ++s_count;
}
String::~String(){
        if(--s_count == 0){
                delete [] data;
                data = NULL;
        }
}
String::String(const String& str):data(str.data){
        ++s_count;
}
String& String::operator=(const String& str){
        if(this != &str){
                data = str.data;
                ++s_count;
        }
        return *this;
}

问题:构造新对象的计数是几?计数器技术会导致构造新对象计数错误。
解决:每个空间应该具有自己的引用计数,而不能所有空间共享一个引用计数。

头文件

class String{
        struct StringBase{
                StringBase(const char* str);
                ~StringBase();
                char* data;
                int count;
        };
public:
        String(const char* str = NULL);
        String(const String& str);
        String& operator=(const String& str);
        ~String();
        size_t size()const;
        friend ostream& operator<<(ostream& os,String const& str);
private:
        StringBase* base;
};

实现

String::StringBase::StringBase(const char* str){
        if(NULL == str){
                data = new char[1];
                data[0] = '';
        }else{
                data = new char[strlen(str)+1];
                strcpy(data,str);
        }
        ++count;
}
String::StringBase::~StringBase(){
        if(--count == 0){
                delete [] data;
                data = NULL;
        }
}

String::String(const char* str){
        base = new StringBase(str);
}
String::~String(){

}
String::String(const String& str):base(str.base){
        base->count++;
}
String& String::operator=(const String& str){
        if(this != &str){
                base->count--;
                base = str.base;
                base->count++;
        }
        return *this;
}
inline size_t String::size()const{
        return strlen(base->data);
}

ostream& operator<<(ostream& os,const String& str){
        return os << static_cast(str.base) << ':' << str.base->data;
}
写时拷贝技术

以上都是拷贝复制操作,如果字符串发生改变,那么才是真正的写时拷贝。
例如:实现+=操作

String& String::operator+=(const String& str){
        base.count--;
        // 一些具体操作...
        base = new StringBase();
        base.count++; 
        return *this;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001814.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号