2012-01-10 111 views
3

我对一些基本的字符串实现有点困惑。我一直在通过消息来源了解内心的工作并学习新事物。我不能完全掌握内存如何管理。std :: string分配策略

从基本字符串实现

  • 原始分配器只是一些小花絮是char类型

    typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc; 
    
  • ...然后在分配代表被放置在分配的缓冲区__size内计算也适合字符

    size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); 
    void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); 
    _Rep *__p = new (__place) _Rep; 
    
  • 这是字符数据是如何从_Rep缓冲

    _CharT* _M_refdata() throw() 
    { 
        return reinterpret_cast<_CharT*>(this + 1); 
    } 
    
  • 设置的字符牵强 - 一种类型的方式

    _M_assign(__p->_M_refdata(), __n, __c); 
    

是什么在困扰我的是,原分配器是char类型,但分配的内存可能包含一个_Rep对象,加上字符数据(不一定是char类型)

此外,为什么(或更确切地说) ES调用_M_refdata知道在字符数据的开始(或结束)是在缓冲器内(即this+1

编辑:不只是this+1内部指针推到下一个位置的_Rep对象之后?

我对内存对齐和铸造有基本的了解,但这似乎超出了我已阅读的任何内容。

任何人都可以帮忙,或者指点我更多内容丰富的阅读材料吗?

回答

0

分配器像C的malloc一样返回指向字节的指针而不是对象。所以,返回类型是char *void *

在C和C++标准的某个地方,有一个条款明确允许在char和任何其他对象类型之间重新解释转换。这是因为C经常需要将对象视为字节数组(当写入磁盘或网络套接字时),并且需要将字节数组视为对象(如分配内存范围或从磁盘读取时)。

为了防止混淆和优化的问题,你不允许到同一char *转换为不同类型的对象,一旦你已经浇铸在char *一个对象类型,你是不允许修改的对象值写入字节。

+0

这与'char'无关。你可以'将所有简单的指针类型'reinterpret_cast'对齐。 – filmor 2012-01-10 20:54:45

+4

@filmor:不正确。这违反了严格的别名规则。 – 2012-01-10 20:56:48

+0

@filmor:这个语言会让你做到这一点,但它并不保证将它编译成你认为它应该做的事情。例如,在将'char *'转换为'double'后,它可能会将double加载到寄存器中。然后你写一些东西给char *'。它*不会*改变'double'的值。 – 2012-01-10 20:59:41

4

您错过了新的展示位置。该生产线

_Rep *__p = new (__place) _Rep; 

初始化为__place_Rep -object。这个空间已经在之前被分配了(意思是一个放置 - new不会自己分配,实际上只是一个构造函数调用)。

C和C++中的指针运算告诉您,this + 1是一个指针,指向sizeof(*this)字节右边的this。由于之前已经分配了(__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)个字节,所以将_Rep对象之后的空间用于字符数据。布局是这样的:

| _Rep | (__capacity + 1) * _CharT |