gpt4 book ai didi

c++ - 如何在 C++ 中接收可变长度数组的函数中传递可变长度数组?

转载 作者:行者123 更新时间:2023-11-28 06:25:22 25 4
gpt4 key购买 nike

我找到了一种在 C++ 中传递可变长度数组的方法。但它在下面的代码中失败了“包装”功能。其实我想在我的项目中包装格式功能。我的代码做错了什么?

测试代码

#include <iostream>
#include <stdarg.h>
#include <string>

void log(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);

int length = _vscprintf(format, argptr);
char* buf_ = new char [length + 1];
int ret = vsnprintf(buf_, 1000, format, argptr);

if (ret >= 0) {
std::cout << buf_ << std::endl;
}

delete[] buf_;
va_end(argptr);
}

void wrap(const char *format, ...)
{
va_list ap;
va_start(ap, format);
log(format, ap);
va_end(ap);
}


int main()
{
log( "direct = %d", 1);
wrap("wrap = %d", 1);

return 0;
}

结果在这里

direct = 1
wrap = 15137088 // what's happen?

最佳答案

I found a way to pass a variable length array in C++

那不是变长数组,也不是真正地道的 C++。 ... 是可变长度参数列表,在 C 中可用。

包装日志函数的最简单合理的方法是可变参数模板,它可以简单地写成:

template <typename... Args>
void wrap(const char *format, Args&&... args) {
log(format, std::forward<Args>(args)...);
}

在日志函数本身中,vsnprintf 返回本应写入 的字节数,以防它填满缓冲区。因此,您始终可以使用乐观的缓冲区大小调用它一次,并在必要时增加缓冲区:您不需要非标准的 _vscprintf。这看起来像:

void log(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);

static const size_t DefaultSize = 200;
// pick some value that makes sense ^^ here
char buf[DefaultSize];
int rv = vsnprintf(buf, DefaultSize, format, argptr);
if (rv < 0) {
// we can't return errors with this prototype:
// should it throw?
return;
}
if (rv >= DefaultSize) {
vector<char> dynbuf(rv+1);
rv = vsnprintf(&dynbuf[0], dynbuf.size(), format, argptr);
std::cout << &dynbuf[0] << std::endl;
} else {
std::cout << buf << std::endl;
}

va_end(argptr);
}

另请注意,wrap 知道其所有参数的类型,但当您调用 C 风格的可变参数函数 log 时,该信息将被丢弃。您可能会将 Boost.Format 视为类型安全的替代方案 - 作为奖励,它将为您管理缓冲区。

关于c++ - 如何在 C++ 中接收可变长度数组的函数中传递可变长度数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28627343/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com