为什么我们不将格式说明符与 cout 一起使用?
Why we don't use format specifiers with cout?
当我们使用 printf 时,我们使用格式说明符(例如 %c,%p(,但是当我们使用 cout 时,我们不使用它们为什么以及在后台做什么,因为我们没有使用它们?
我知道它们在 c 和 c++ 中的使用方式不同,但我仍然想知道格式化是如何在 cout 中完成的,而它是在 printf 中通过格式说明符完成的。
在C++中,ostream::operator<<
对于不同的类型是重载的。您可以尝试挖掘标准库实现以准确查看它的外观,但它将归结为大致等效于以下内容的内容:
class ostream
{
public:
ostream& operator<<( int val );
ostream& operator<<( float val );
ostream& operator<<( const char* val );
};
真正的实现将比上述复杂得多,但大致就是这个想法。希望这种实现比printf更有效,因为编译器可以在适当的时候更容易地内联代码。请考虑以下事项:
int val = 0;
printf("%dn", val);
std::cout << val << std::endl;
在 printf 的情况下,一个天真编译的程序(由不了解格式说明符的编译器编译的程序(必须在运行时解析 "%d"。与 std::cout 调用形成对比,在这种情况下,编译器只需要确定要使用的重载,然后就可以内联代码。
也就是说,c 标准中没有任何内容说编译器无法在编译时解析格式说明符(如果它们可用(。实际上,使用格式说明符和 c++ ostream 的 c 样式日志记录库之间的性能差异是......细致 入微。
因为printf
设计正确,cout
内部状态令人讨厌。使用 printf
,您希望每个参数格式化的方式在格式字符串中是明确的;没有隐藏状态。使用 cout
,您还可以控制格式(如字段宽度等(,但它是 iostream 对象中的隐藏状态。如果流的上一个用户将其保留为非默认状态,则除非显式重置状态,否则您将执行错误的操作。您甚至不想考虑在多线程用例中会发生什么......
基本上答案是运算符重载。函数可以具有相同的名称,只要它们采用不同的参数。 operator<<
是您想知道的函数名称。编译器知道您尝试打印的内容的类型,并调用正确的operator<<
。
这就是为什么如果你创建自己的对象,你不能只写std::cout << yourObject;
并期望它按照你想要的方式工作。您必须指定应如何打印,
ostream& operator<<(ostream& os, const YourObject& rhs) {
os << rhs.member;
return os;
}
但是,令人高兴的是,在像int
这样的情况下,这已经在幕后为您完成了。请参阅:http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt2 以获取提供的重载的完整列表。
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 如何将enable-if与模板参数和参数包一起使用
- 如何将PERF_AMPLE_READ与mmap一起使用
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- std::cout.imbue()多重调用
- 逗号操作员如何与C 中的COUT一起使用
- 将逻辑 OR 与 cout 运算符一起使用
- 如何将按位移位与 cout 一起使用
- C++:当与 std::cout 一起使用时,constexpr 函数在编译时不会计算
- 将字符串转换为char,当我cout时,它是正确的,但是当我将chdir与char一起使用时,它不起作用
- 为什么 std::nullptr_t 不能与 std::cout 一起使用C++?
- 为什么将我的打印方法与std::cout一起使用会导致错误
- 在C++中将cout与变量一起使用时出错
- 在交互式程序中将预处理器指令与 cout 和字符串流一起使用 - C++
- 为什么我们不将格式说明符与 cout 一起使用?
- 如何将 std::cout 与我的(模板化)类一起使用
- C++:将'this'指针与"get"函数一起使用以替换 cout 语句的可能性
- 将cout与类中的两个表达式一起使用
- 除非我通过data()或C_str()运行cout,否则无法将它与C++字符串一起使用
- 使用 "<<" 或 "+" 将字符串放在一起"cout"