调整 std::string 大小而不初始化内存

问题描述 投票:0回答:1

我正在使用 C 例程写入 std::string 的数据字段。这是一个人为的示例,实际上我通过网络获取一个非空终止的字符串及其大小:

#include <string>
#include <cstdio>
#include <cstring>

const char* str = "Some examplory string.."; 

int main()
{
    std::string some_str;
    some_str.resize(strlen(str));
    std::strcpy(&some_str.front(), str);
    printf(some_str.c_str());
}

现在根据 cppref

resize()
没有重载,它只是调整大小并且不会用 ' ' 或其他东西初始化内存。但如果我所做的只是再次覆盖它,为什么我要为此付费呢?可以通过某种方式避免这种情况吗?

c++ c++20 stdstring
1个回答
0
投票

对于 c++23,我们有 resize_and_overwrite

对于旧标准,让我们破解它!

它在 gcc5+、clang12+、msvc 1921+ 上运行良好

// Our hacker function, resize a std::string without initializing memory
// (but still has '\0' in the end of string)
inline void resize(std::string& str, std::size_t sz);

#if __cpp_lib_string_resize_and_overwrite >= 202110L
    inline void resize(std::string& str, std::size_t sz) {
        str.resize_and_overwrite(sz, [](char*, std::size_t sz) {
            return sz;
            });
    }
#elif (defined(__clang_major__) && __clang_major__ <= 11) ||(defined(_MSC_VER)&& _MSC_VER<=1920)
    // old clang has bug in global friend function. discard it.
    // old msvc don't support visit private, discard it.
    inline void resize(std::string& str, std::size_t sz) { str.resize(sz); }
#else

#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
    template <typename Money_t, Money_t std::string::* p>
    class string_thief {
    public:
        friend void string_set_length_hacker(std::string& bank, std::size_t sz) {
            (bank.*p)(sz);
        }
    };
#elif defined(_MSVC_STL_VERSION)
    template <typename Money_t, Money_t std::string::* p>
    class string_thief {
    public:
        friend void string_set_length_hacker(std::string& bank, std::size_t sz) {
            (bank.*p)._Myval2._Mysize = sz;
        }
    };
#endif

#if defined(__GLIBCXX__)  // libstdc++
    template class string_thief<void(std::string::size_type),
        &std::string::_M_set_length>;
#elif defined(_LIBCPP_VERSION)
    template class string_thief<void(std::string::size_type),
        &std::string::__set_size>;
#elif defined(_MSVC_STL_VERSION)
    template class string_thief<decltype(std::string::_Mypair),
        &std::string::_Mypair>;
#endif

#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || \
    defined(_MSVC_STL_VERSION)
    void string_set_length_hacker(std::string& bank, std::size_t sz);
#endif

    inline void resize(std::string& str, std::size_t sz) {
#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || \
    defined(_MSVC_STL_VERSION)
        str.reserve(sz);
        string_set_length_hacker(str, sz);
        str[sz] = '\0';
#else
        str.resize(sz);
#endif
    }
#endif
© www.soinside.com 2019 - 2024. All rights reserved.