作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我找到了一种在 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/
我是一名优秀的程序员,十分优秀!