小字符串优化(调试与发布模式)

Small String Optimisation (Debug vs Release mode)

我一直在使用此示例脚本检查小字符串优化(在 MSVC 2019 中):

#include <string>

void* operator new(size_t size)
{
    std::printf("global op new called, size = %zu\n", size);
    void* ptr = std::malloc(size);

    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}

int main()
{
    std::string test = "small value";
    return 0;
}

请注意,我从 https://en.cppreference.com/w/cpp/memory/new/operator_new 中提取了 void* operator new(size_t size)

Release 模式下,优化按预期工作(即 new 未被调用),但在 Debug 模式下该脚本实际打印 global op new called, size = 16。深入研究后,这似乎是由于 header xmemory:

中的代码段所致
#if _ITERATOR_DEBUG_LEVEL == 0
  #define _GET_PROXY_ALLOCATOR(_Alty, _Al) _Fake_allocator()
  template <class _Alloc>
  using _Container_proxy_ptr = _Fake_proxy_ptr_impl;
#else // _ITERATOR_DEBUG_LEVEL == 0
  #define _GET_PROXY_ALLOCATOR(_Alty, _Al) static_cast<_Rebind_alloc_t<_Alty, _Container_proxy>>(_Al)
  template <class _Alloc>
  using _Container_proxy_ptr = _Container_proxy_ptr12<_Rebind_alloc_t<_Alloc, _Container_proxy>>;
#endif // _ITERATOR_DEBUG_LEVEL == 0

我们可以看到在Release模式下(即_ITERATOR_DEBUG_LEVEL == 0)我们使用_Fake_proxy_ptr_impl,而在Debug 模式我们使用 _Container_proxy_ptr12 它使用 new.


我的问题很简单:为什么DebugRelease模式有这个区别?

小字符串优化在调试模式下仍然存在。 如果我们创建一个更大的 string

std::string test = "large value.large value.large value.large value.";

然后我们得到实际的string分配

global op new called, size = 64

在调试和发布版本中。

您正在观察的是 iterator debugging 的容器代理分配(从 #if _ITERATOR_DEBUG_LEVEL 可以看出)

struct _Container_proxy { // store head of iterator chain and back pointer

您可以通过使用 /D _ITERATOR_DEBUG_LEVEL=0 构建来禁用迭代器调试(但随后它将对所有容器禁用,vectormap 等也会被禁用)。