Rus*_*lan 3 c++ string fstream ofstream
我试图将一些调试输出添加到C++ 03项目中并得到一些奇怪的结果.这是简化的测试代码:
#include <fstream>
int main()
{
{
std::ofstream file("/tmp/test.txt");
file << "hello" << " ... OK, this works\n";
}
std::ofstream("/tmp/test.txt",std::ios_base::app) << "hello"
<< " ... no, I mean hello!\n";
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,这是我在编译后得到的:
$ g++ test.cpp -o test && ./test && cat /tmp/test.txt
hello ... OK, this works
0x80487fe ... no, I mean hello!
Run Code Online (Sandbox Code Playgroud)
为什么在将字符串输出到未命名std::ofstream对象的情况下会得到十六进制数?为什么第二个字符串的后续输出有效?
operator<<我们用于传递C字符串的常用方法std::ostream被声明为自由函数
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
Run Code Online (Sandbox Code Playgroud)
未命名的std::ofstream对象是临时变量,临时变量不能绑定到nonconst引用,因此此运算符重载不参与重载决策.而是采用最接近的匹配,即成员函数
std::basic_ostream& std::basic_ostream::operator<<(const void*);
Run Code Online (Sandbox Code Playgroud)
,它采用类型擦除指针,只打印其值.由于可以在对象是临时对象的情况下调用成员函数,因此可以解决这个问题.这解释了输出中的十六进制数.现在,该运算符返回一个引用std::basic_ostream&.由于这是不再临时对象和是代替一些非const对象的引用,通常的自由功能过载operator<<,这需要const char*,可以成功地调用.这就是为什么第二个字符串按预期打印的原因.
请注意,由于C++ 11代码将按预期工作,因为我们有一个额外的重载operator<<,它采用右值引用:
template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
const T& value );
Run Code Online (Sandbox Code Playgroud)
,临时确实绑定到右值引用.
要使代码在C++ 03中工作,可以使用成员函数std::ostream::flush(),该函数返回对象的nonconst引用,并且对该对象没有任何用户可见的副作用fstream:
#include <fstream>
int main()
{
std::ofstream("/tmp/test.txt").flush() << "hello"
<< " ... OK, this now works too\n";
}
Run Code Online (Sandbox Code Playgroud)