Chinaunix首页 | 论坛 | 博客
  • 博客访问: 543080
  • 博文数量: 493
  • 博客积分: 2891
  • 博客等级: 少校
  • 技术积分: 4960
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-17 17:11
文章分类

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 18:30:06

4 经验总结:预防措施和规范建议
STL中为了提高性能大量采用写时才拷贝(Copy-On-Write)技术,该技术使用了"引用计数",有一个变量类似于RefCnt。当第一个类构造时,string的构造函数会根据传入的参数从堆上分配内存,当有其它对象被拷贝构造时候它们会共享这块内存,这个计数会自动累加,当有对象被析构时,这个计数会减一,直到最后一个对象析构时,此时的RefCnt为1或是0,此时,程序才会真正的Free这块从堆上分配的内存。在共享同一块内存的对象发生内容改变时,就会发生Copy-On-Write,比如string类的[]、=、+=、+、操作符赋值,还有string类中诸如insert、replace、append等成员函数,发生Copy-On-Write时候string类的拷贝构造函数会重新分配一块内存区,将新的内容写入新的内存区间中,并将原有内存区间的引用计数减一。
在使用STL时候了解STL中的Copy-On-Write技术,避免在使用STL中的类时候引起一些内存问题。在Windows下、Linux、Solaris下都存在这种机制,AIX下则没有使用这种机制。
5 备注
STL库其他容器也有类似的问题需要注意;下面是string类的构造函数和拷贝构造函数以及重载操作符函数代码,供参考,里面真实表现了copy-on-write和共享内存技术;
//构造函数(分存内存)
string::string(const char* tmp)
{
    _Len = strlen(tmp);
    _Ptr = new char[_Len+1+1];
    strcpy( _Ptr, tmp );
    _Ptr[_Len+1]=0;  // 设置引用计数 
}
//拷贝构造(共享内存)
string::string(const string& str)
{
    if (*this != str)
    {
        this->_Ptr = str.c_str();   //共享内存
        this->_Len = str.szie();
        this->_Ptr[_Len+1] ++;  //引用计数加一
    }
}
//写时才拷贝Copy-On-Write
char& string::operator[](unsigned int idx)
{
    if (idx > _Len || _Ptr == 0 )
    {
        static char nullchar = 0;
        return nullchar;
    }
    _Ptr[_Len+1]--;   //引用计数减一
    char* tmp = new char[_Len+1+1];
    strncpy( tmp, _Ptr, _Len+1);
    _Ptr = tmp;
    _Ptr[_Len+1]=0; // 设置新的共享内存的引用计数
    return _Ptr[idx];
}
6 考核点
Copy-on-Write机制
7 试题
关于下面这段代码(VC6.0)的结果说法正确的是:(D)
main()
{
    string str1 = "hello world";
    string str2 = str1;
    printf ("address1: %x\n", str1.c_str() );
    printf ("address2: %x\n", str2.c_str() );
    str1[1]='a';
    printf ("address3: %x\n", str1.c_str() );
    str2[2]='b';
    printf ("address4: %x\n", str2.c_str() );
    return 0;
}
A. 由于str1和str2是2个不同的对象,所以address1和address2不一致;
B. address3和address1的内存地址空间一致;
C. address3和address4的内存地址空间一致;
D. address1和address3的内存地址空间不一致。
阅读(237) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~