Why is constexpr of std::wstring().capacity() not equal to std::wstring().capacity()?

Viewed 746

I'm not sure if I'm too naïve or simply too unknowing.

But why does the following differ?

constexpr auto nInitialCapacity1 = std::wstring().capacity();
const auto     nInitialCapacity2 = std::wstring().capacity();

In Visual Studio 2022/17.0.5 the code above results in:

nInitialCapacity1 = 8
nInitialCapacity2 = 7

Why is the result of the constexpr (compile time) version not equal to the const version of the call?

Thanks for any explanation!

2 Answers

Microsoft's STL disables short string optimisation in constant evaluated contexts, so it allocates memory instead.

The allocations are always one more than a power of two, so the capacity (which excludes the last L'\0') is always a power of two.

In the non-constant-evaluated version, the short string buffer can hold 8 characters, one of which is a L'\0', so the capacity is 7.

Update by new experiences and observations:

  • The contents of the disassembly window showed, that the result of the const-call to std::wstring::capacity is 8!
  • But the watch window and the tooltip of the variable show 7.

The hypothesis of a colleague is, that the debugger calls the constexpr method capacity non-const, gets the differing result of 7 and visualizes it.

A reason to look into the disassembly window was the unexpected behavior in the following code:

const auto nInitCap = std::wstring().capacity();
const auto nCap     = str.capacity();

if (nCap != nInitCap)
    std::wcout << "capacity " << nCap << "is not equal to the initial capacity " << nInitCap << std::endl;

if (nCap > nInitCap)
    std::wcout << "capacity " << nCap << "is greater than the initial capacity " << nInitCap << std::endl;

The debugger showed for the variables:

nInitCap: 7
nCap:     7

But the code printed out:

capacity 7 is not equal to the initial capacity 7

The capacity call to the const-constructed temporary object returns 8, as to be seen in the disassembly, so the behavior is explainable, even if the debugger of VS2022 17.0.5 shows 7

Related