跨流行工具链的标准容器重新分配乘数

发布于 2024-10-25 12:33:12 字数 391 浏览 3 评论 0原文

当内部容量耗尽时,std::basic_stringstd::vector 等容器会执行自动重新分配。标准规定,重新分配后,.capacity() >= .size()

主流工具链在执行重新分配时使用的实际乘数有哪些?


更新

到目前为止,我有:

Dinkumware:1.5(附带 MSVS 和可能的 ICC)

GNU libstdc++:2(随 GCC 和可能的 ICC 一起提供)

RW/Apache stdcxx:1.618(又名 φ)

STL 端口:2

Containers like std::basic_string and std::vector perform automatic re-allocations when internal capacity runs out. The standard specifies that, after a re-allocation, .capacity() >= .size().

What are some of the actual multipliers used by mainstream toolchains when performing re-allocations?


Update

So far, I have:

Dinkumware: 1.5 (ships with MSVS and possibly ICC)

GNU libstdc++: 2 (ships with GCC and possibly ICC)

RW/Apache stdcxx: 1.618 (aka φ)

STLport: 2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

刘备忘录 2024-11-01 12:33:12

老问题的新答案。

理由:可以通过编程方式并使用在线编译器相对容易地回答这个问题。这里有一个程序可以帮助您回答这个问题:

#include <climits>
#include <cstddef>
#include <cstdlib>
#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
#include <type_traits>
#include <limits>
#include <vector>
#include <string>

template <typename T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}

template <class C>
void
test()
{
    C c;
    std::cout << type_name<C>() << ":\n";
    std::size_t c0 = c.capacity();
    std::cout << "    Initial capacity is " << c0 << '\n';
    c.resize(c0);
    for (int i = 0; i < 10; ++i)
    {
        c.push_back(typename C::value_type{});
        std::size_t c1 = c.capacity();
        if (c0 != 0)
        {
            float f = static_cast<float>(c1)/c0;
            std::cout << "    growth factor appears to be " << f << '\n';
        }
        c0 = c1;
        c.resize(c0);
    }
}

int
main()
{
    test<std::vector<int>>();
    test<std::string>();
}

大多数复杂性都是不必要的,因为它只是为了让 type_name 工作。

libstdc++:

http://melpon.org/wandbox/permlink/njaIG2uiR2vlCLZz

似乎都回答了实心 2。

VS:

http://webcompiler.cloudapp.net

两者都非常接近 1.5向量和字符串。

libc++

http://melpon.org/wandbox/permlink/mXshrLJHgNuvE1mD

对于向量和字符串来说都非常接近 2。

请注意,该程序还告诉您 string 的短字符串缓冲区是什么:libstdc++ 和 VS 均为 15,libc++ 为 22。

New answer for an old question.

Rationale: The answer can be answered programatically, and with online compilers, relatively easily. Here is a program that can help you answer this question:

#include <climits>
#include <cstddef>
#include <cstdlib>
#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
#include <type_traits>
#include <limits>
#include <vector>
#include <string>

template <typename T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}

template <class C>
void
test()
{
    C c;
    std::cout << type_name<C>() << ":\n";
    std::size_t c0 = c.capacity();
    std::cout << "    Initial capacity is " << c0 << '\n';
    c.resize(c0);
    for (int i = 0; i < 10; ++i)
    {
        c.push_back(typename C::value_type{});
        std::size_t c1 = c.capacity();
        if (c0 != 0)
        {
            float f = static_cast<float>(c1)/c0;
            std::cout << "    growth factor appears to be " << f << '\n';
        }
        c0 = c1;
        c.resize(c0);
    }
}

int
main()
{
    test<std::vector<int>>();
    test<std::string>();
}

Most of the complexity is a bit unnecessary as it is just to get type_name working.

libstdc++:

http://melpon.org/wandbox/permlink/njaIG2uiR2vlCLZz

appears to answer a solid 2 for both vector and string.

VS:

http://webcompiler.cloudapp.net

is very close to 1.5 for both vector and string.

libc++

http://melpon.org/wandbox/permlink/mXshrLJHgNuvE1mD

is very close to 2 for both vector and string.

Note that this program also tells you what the short string buffer is for string: 15 for both libstdc++ and VS, and 22 for libc++.

微暖i 2024-11-01 12:33:12

Dinkumware STL(随 Visual Studio 一起提供)使用 1.5 乘数,Gcc 使用 2。我无法真正说出其余的数字,但我认为这些是最常用的数字。 (IIRC,我读过一次,大多数实现使用了2)

作为附带评论,您正确地将其称为乘数,因为标准要求增长(至少)几何。

Dinkumware STL (shipped with Visual Studio) uses a 1.5 multiplier, Gcc uses 2. I cannot really tell for the rest, but I think those are the most often used numbers. (IIRC, I read once that most implementations used 2)

As a side comment, you are correctly calling it a multiplier since the standard requires the growth to be (at least) geometrical.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文