C++ 11将堆数组移至std :: string

发布于 2025-02-13 22:38:08 字数 1592 浏览 0 评论 0原文

在stackoverflow上查看其他答案,答案可能只是一个拒绝,但请在标记重复之前幽默我。

因此,我希望能够格式化字符串SNPRINTF样式,如下所示,但只能进行单个堆分配。

许多示例说要触摸std :: string :: data()或std :: string :: c_str(),但显然您不应该这样做,因为它确实是不安全的,因为这是管理内存的,因此参考和指针是不能保证是恒定的内存地址。

也无法使用std ::格式,因为我没有运行C ++ 20

#include <cstdlib>
#include <iostream>
#include <string>
#include <cstdarg>
#include <cstdio>

std::string Somefunction(const char* formatstring, ...){
    //Let's get the actual size, because recursively reallocating to get this is not efficient
    va_list sizeVl;
    va_start(sizeVl, formatstring);
    const int formatSize = _vscprintf(formatstring, sizeVl);
    va_end(sizeVl);

    if (formatSize < 1){
        return{};
    }

    //Some object to put the memory on the stack, I'll use a char, but could be vector<char> etc, 
    //whatever achieves the goal
    char* tempString = new char[formatSize + 1];

    va_list vl;
    va_start(vl, formatstring);
    const int actualLength = vsnprintf(tempString, formatSize, formatstring, vl);
    va_end(vl);

    if (actualLength <= formatSize){
        tempString[actualLength] = '\0';
        //vv--- I really don't want to reallocate on the heap, I already have some heap memory
        //vv--- Move semantics 101
        //std::string output = MOVE(tempString); 
        std::string output("Ideally I move the memory here");
        return output;
    }
    delete[] tempString;
    return{};
}

有任何想法,或者答案真的只是STD :: String不是您的容器,如果您想要此功能?

我可以在vsnprintf函数中安全使用任何容器作为chnprintf ::字符串将安全移动的char阵列吗?

Looking around other answers on stackoverflow the answer may just be a no, but please humor me before marking it a duplicate.

So I want to be able for format a string snprintf style as shown below, but only make a single heap allocation.

Lots of examples say to touch the std::String::data() or std::String::c_str() but obviously you shouldn't do this as it's really unsafe, as this is managed memory, so references and pointers are not guaranteed to be constant memory addresses.

Also cannot use std::format as I'm not running C++20

#include <cstdlib>
#include <iostream>
#include <string>
#include <cstdarg>
#include <cstdio>

std::string Somefunction(const char* formatstring, ...){
    //Let's get the actual size, because recursively reallocating to get this is not efficient
    va_list sizeVl;
    va_start(sizeVl, formatstring);
    const int formatSize = _vscprintf(formatstring, sizeVl);
    va_end(sizeVl);

    if (formatSize < 1){
        return{};
    }

    //Some object to put the memory on the stack, I'll use a char, but could be vector<char> etc, 
    //whatever achieves the goal
    char* tempString = new char[formatSize + 1];

    va_list vl;
    va_start(vl, formatstring);
    const int actualLength = vsnprintf(tempString, formatSize, formatstring, vl);
    va_end(vl);

    if (actualLength <= formatSize){
        tempString[actualLength] = '\0';
        //vv--- I really don't want to reallocate on the heap, I already have some heap memory
        //vv--- Move semantics 101
        //std::string output = MOVE(tempString); 
        std::string output("Ideally I move the memory here");
        return output;
    }
    delete[] tempString;
    return{};
}

Any thoughts, or is the answer really just std::string isn't the container for you if you want this functionality?

Is there any container I can use safely as a char array in the vsnprintf function that std::String will move safely?

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

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

发布评论

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

评论(1

情未る 2025-02-20 22:38:08

问题中的注释正确指示您实例化具有特定大小的字符串,并使用.data()&amp; [0]操作员获取所需的东西。

让我建议一个更简单的解决方案,并具有约束。考虑到您的输出字符串具有一定合理的长度,并且您可以使用大量的堆栈内存。因此,请使用固定的长度温度缓冲区来进行printf样式格式。 20K并不是在堆栈上分配的数量不合理的字节。

然后返回一个std :: String使用C String构造器的复制版的实例。

std::string Somefunction(const char* formatstring, ...){

   const size_t TEMP_SIZE = 20000;

    va_list vargs = {};

    va_start(vargs, formatstring);

    char buffer[TEMP_SIZE];
    vsnprintf(buffer, TEMP_SIZE, formatstring, vargs);

    va_end(vargs);

    return std::string(buffer);
}

如果需要的话,您总是可以将缓冲区的大小从20000增加到更大。但是我猜你的琴弦永远不会变得那么大。而且,如果他们这样做,您不希望我猜是您的日志文件中的很多字节。

The comments in your question are correctly directing you to instantiate a string with a specific size and use the .data() or &[0] operator to get what you need.

Let me suggest a simpler solution with a constraint. Consider that your output strings have some reasonable length and that you have plenty of stack memory to work with. So use a fixed length temp buffer to do your printf style formatting. 20K is not an unreasonable number of bytes to allocate on the stack.

Then return an instance of a std::string using the copy from C string constructor at the very end.

std::string Somefunction(const char* formatstring, ...){

   const size_t TEMP_SIZE = 20000;

    va_list vargs = {};

    va_start(vargs, formatstring);

    char buffer[TEMP_SIZE];
    vsnprintf(buffer, TEMP_SIZE, formatstring, vargs);

    va_end(vargs);

    return std::string(buffer);
}

You could always increase the buffer size from 20000 to something larger if you needed it. But I'm guessing your strings never get that big. And if they did, you wouldn't want that many bytes in what I'm guessing is your log file.

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