为什么std :: string分配两次? [英] Why std::string allocating twice?

查看:117
本文介绍了为什么std :: string分配两次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为 std :: string std :: vector 写了一个自定义分配器,如下所示:

I wrote a custom allocator for std::string and std::vector as follows:

#include <cstdint>
#include <iterator>
#include <iostream>

template <typename T>
struct PSAllocator
{
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    template<typename U>
    struct rebind {typedef PSAllocator<U> other;};

    PSAllocator() throw() {};
    PSAllocator(const PSAllocator& other) throw() {};

    template<typename U>
    PSAllocator(const PSAllocator<U>& other) throw() {};

    template<typename U>
    PSAllocator& operator = (const PSAllocator<U>& other) { return *this; }
    PSAllocator<T>& operator = (const PSAllocator& other) { return *this; }
    ~PSAllocator() {}


    pointer allocate(size_type n, const void* hint = 0)
    {
        std::int32_t* data_ptr = reinterpret_cast<std::int32_t*>(::operator new(n * sizeof(value_type)));
        std::cout<<"Allocated: "<<&data_ptr[0]<<" of size: "<<n<<"\n";
        return reinterpret_cast<pointer>(&data_ptr[0]);
    }

    void deallocate(T* ptr, size_type n)
    {
        std::int32_t* data_ptr = reinterpret_cast<std::int32_t*>(ptr);
        std::cout<<"De-Allocated: "<<&data_ptr[0]<<" of size: "<<n<<"\n";
        ::operator delete(reinterpret_cast<T*>(&data_ptr[0]));
    }
};

然后我运行以下测试用例:

Then I ran the following test case:

int main()
{
    typedef std::basic_string<char, std::char_traits<char>, PSAllocator<char>> cstring;

    cstring* str = new cstring();
    str->resize(1);
    delete str;

    std::cout<<"\n\n\n\n";

    typedef std::vector<char, PSAllocator<char>> cvector;

    cvector* cv = new cvector();
    cv->resize(1);
    delete cv;
}

对于任何奇怪的原因,它继续打印:

For whatever odd reason, it goes on to print:

Allocated: 0x3560a0 of size: 25
Allocated: 0x3560d0 of size: 26
De-Allocated: 0x3560a0 of size: 25
De-Allocated: 0x3560d0 of size: 26




Allocated: 0x351890 of size: 1
De-Allocated: 0x351890 of size: 1

那么为什么它为 / code>和更多的字节?

So why does it allocate twice for std::string and a lot more bytes?

我在Windows 8上使用g ++ 4.8.1 x64 sjlj: http://sourceforge.net/projects/mingwbuilds/

I'm using g++ 4.8.1 x64 sjlj on Windows 8 from: http://sourceforge.net/projects/mingwbuilds/.

推荐答案

我不能重现double分配,因为显然我的libstdc ++不分配任何东西空字符串。调整大小然而分配26字节,gdb帮助我识别如何组合

I can't reproduce the double allocation, since apparently my libstdc++ does not allocate anything at all for the empty string. The resize however does allocate 26 bytes, and gdb helps me identifying how they are composed:

size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
                   (     1     + 1) *     1          +     24

a href =http://repo.or.cz/w/official-gcc.git/blob/9bcca88e24e64d4e23636aafa3404088b13bcb0e:/libstdc++-v3/include/bits/basic_string.h#l134 =nofollow> _Rep 表示,其由下列数据成员组成:

So the memory is mostly for this _Rep representation, which in turn consists of the following data members:

size_type    _M_length;   // 8 bytes
size_type    _M_capacity; // 8 bytes
_Atomic_word _M_refcount; // 4 bytes

我想最后四个字节只是为了对齐,已经错过了一些数据元素。

I guess the last four bytes is just for the sake of alignment, but I might have missed some data element.

我想这个 _Rep 结构在堆上分配的主要原因是它可以在字符串实例之间共享,也可以避免空字符串,因为我的系统上缺少第一个分配。

I guess the main reason why this _Rep structure is allocated on the heap is that it can be shared among string instances, and perhaps also that it can be avoided for empty strings as the lack of a first allocation on my system suggests.

要找出原因您的实现不使用此空字符串优化,请查看默认构造函数。它的实现似乎取决于 _GLIBCXX_FULLY_DYNAMIC_STRING 的值,这在您的设置中显然是非零的。我不建议直接更改该设置,因为它以下划线开始,因此被认为是私有的。但您可能会发现一些公开设置影响此值。

To find out why your implementation doesn't make use of this empty string optimization, have a look at the default constructor. Its implementation seems to depend on the value of _GLIBCXX_FULLY_DYNAMIC_STRING, which apparently is non-zero in your setup. I'd not advise changing that setting directly, since it starts with an underscore and is therefore considered private. But you might find some public setting to affect this value.

这篇关于为什么std :: string分配两次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆