Mar*_*ius 6 c++ iostream temporary stringstream
我正在创建一个包含以下部分的记录器:
// #define LOG(x) // for release mode
#define LOG(x) log(x)
log(const string& str);
log(const ostream& str);
Run Code Online (Sandbox Code Playgroud)
有了这样的想法:
LOG("Test");
LOG(string("Testing") + " 123");
stringstream s;
LOG(s << "Testing" << 1 << "two" << 3);
Run Code Online (Sandbox Code Playgroud)
这一切都按预期工作,但当我这样做时:
LOG(stringstream() << "Testing" << 1 << "two" << 3);
Run Code Online (Sandbox Code Playgroud)
这是行不通的:
void log(const ostream& os)
{
std::streambuf* buf = os.rdbuf();
if( buf && typeid(*buf) == typeid(std::stringbuf) )
{
const std::string& format = dynamic_cast<std::stringbuf&>(*buf).str();
cout << format << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
导致'format'包含垃圾数据而不是通常正确的字符串.
我认为这是因为<<运算符返回的临时ostream比它来自的字符串流更长.
还是我错了?
(为什么string()以这种方式工作?是因为它返回对它自己的引用吗?我假设是的.)
我真的很想这样做,因为我在登录发布模式时会省去额外的分配.
任何以这种方式完成任务的指针或技巧都会受到欢迎.在我的实际解决方案中,我有许多不同的日志功能,它们都比这更复杂.所以我更希望在调用代码中以某种方式实现它.(如果可能的话,不要修改我的#define)
只是给出一个想法,一个我的实际#defines的例子:
#define LOG_DEBUG_MSG(format, ...) \
LogMessage(DEBUG_TYPE, const char* filepos, sizeof( __QUOTE__( @__VA_ARGS__ )), \
format, __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
它匹配varargs类似printf的日志函数,它采用char*,string()和ostream()以及采用string(),exception()和HRESULT的非vararg函数.
我想我知道发生了什么.这会产生预期的输出:
log(std::stringstream() << 1 << "hello");
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
log(std::stringstream() << "hello" << 1);
Run Code Online (Sandbox Code Playgroud)
(它写一个十六进制数字,后跟"1"数字)
解释的几个要素:
在上面的代码中,std :: stringstream()创建一个临时(rvalue).它的生命周期没有问题,因为它必须持续它所声明的整个表达式(即,直到调用log()返回).
在第一个示例中,一切正常,因为首先调用成员运算符<<(int),然后返回的引用可以传递给operator <<(ostream&,const char*)
在第二个例子中,operator <<(不能用"std :: stringstream()"作为第一个参数调用,因为这需要将它绑定到非const引用.但是,成员运算符<<(void*)没关系,因为它是会员.
顺便说一句:为什么不将log()函数定义为:
void log(const std::ostream& os)
{
std::cout << os.rdbuf() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
改变你的LOG()宏:
#define LOG(x) do { std::stringstream s; s << x; log(s.str()); } while(0)
Run Code Online (Sandbox Code Playgroud)
这将允许您在调试日志中使用以下语法,因此您不必手动构造字符串流.
LOG("Testing" << 1 << "two" << 3);
Run Code Online (Sandbox Code Playgroud)
然后将它定义为什么都没有发布,你将没有额外的分配.
| 归档时间: |
|
| 查看次数: |
2631 次 |
| 最近记录: |