【问题标题】:Having hard time understanding std::basic_string memory allocation很难理解 std::basic_string 内存分配
【发布时间】:2018-04-14 06:12:51
【问题描述】:

我目前正在学习 STL,我遇到了一位老师制作的示例。

template <class T>
struct SpyAllocator : std::allocator<T>
{
typedef T   value_type;

SpyAllocator(/*vector args*/) = default;

template<class U>
SpyAllocator(const SpyAllocator<U>& other){}

template<class U>
struct rebind
{
    using other = SpyAllocator<U>;
};

T*  allocate(std::size_t n)
{
    T* p = (T*) new char[sizeof(T) * n];

    memorySpy.NotifyAlloc(sizeof(T), n, p);
    return p;
};

void    deallocate(T* p, std::size_t n)
{
    memorySpy.NotifyDealloc(p, n);
    delete (char*)p;
}

typedef T*          pointer;
typedef const T*    const_pointer;
typedef T&          reference;
typedef const T&    const_reference;
};

template <class T, class U>
bool    operator==(const SpyAllocator<T>&, const SpyAllocator<U>&) { return 
false; }

template <class T, class U>
bool    operator!=(const SpyAllocator<T>&, const SpyAllocator<U>&) { return 
false; }

上面是他的分配器实现。

#define String      std::basic_string<char, std::char_traits<char>, SpyAllocator<char>>

他将std::basic_string定义为String

在main.cpp文件中,

int main()
{
    DO(String s1 = "Bonjour");
    DO(String s2 = " le monde !");
    DO(String s3 = s1 + s2);
    printf("s3 : %s\n", s3.c_str());

    printf("\nDestroy vector\n\n");
    return 0;
}

他正在测试 + 运算符和复制构造函数,结果是

String s1 = "Bonjour"

String s2 = " le monde !"

String s3 = s1 + s2
*** Allocate block 1 : 31 elem of 1 bytes

s3 : Bonjour le monde !

Destroy vector

*** Deallocate block 1 : 31 elem of 1 bytes

我的问题是:

1-我统计了String s1String s2的字符数(包括\0),是19个,但分配了31个。 Allocate block 1 : 31 elem of 1 bytes

这背后的原因是什么?

2- String s1String s2 构造函数似乎没有分配任何内存,但 String s1String s2 仍然有值。

这怎么可能?

感谢您的宝贵时间!

【问题讨论】:

  • #define String ... 真是个坏主意。不要为此使用预处理器,使用类型别名:using String = ...(只需将 #define String 完全更改为 using String = 即可满足您的所有需求)
  • @Justin,谢谢你的评论,我会记住的。但它是由我的一位老师制作的。
  • "...没有分配任何内存..." 查找:“小字符串优化”(小字符串在 std::string 类中直接分配不上通过分配器的堆)。字符串(和向量)有时也会增长所需空间的倍数。 (1.6 和 2 是公倍数)
  • 我认为你的老师犯了一个错误,因为他将new[]delete配对,即UB。
  • 谢谢@Richard Critten!从昨天开始我就一直在研究这个问题,但无法弄清楚背后的原因。你刚刚拯救了我的一天!

标签: c++ stl stdstring


【解决方案1】:

当我们查看 STDLib

basic_string.h 时,我们会得到什么
enum
{
    _S_local_capacity = 15 / sizeof(_CharT)
};

union
{
    _CharT _M_local_buf[_S_local_capacity + 1];
    size_type _M_allocated_capacity;
};

We know that std::string is a typedef for a specialization of a std::basic_string with char type.

basic_string contains a 15 bytes fixed buffer for short strings then we +1 for the \0. 因此,当我们连接存储在小缓冲区中的 2 个字符串时,它将连接整个字符串,然后为 \0 添加 +1。所以它将是 15 + 15 + 1 = 31。

这是我从basic_string.h的阅读中了解到的

【讨论】:

  • 感谢您的澄清!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多