如果我只想string
在屏幕上打印一个,我可以使用以下两种方式来做到这一点:
printf("abc");
std::cout << "abc" << std::endl;
情况是,在上面显示的示例中,使用printf
over是否有优势std::cout
,反之亦然?
如果我只想string
在屏幕上打印一个,我可以使用以下两种方式来做到这一点:
printf("abc");
std::cout << "abc" << std::endl;
情况是,在上面显示的示例中,使用printf
over是否有优势std::cout
,反之亦然?
printf
及其相关的朋友是 C 函数。它们在 C++ 中工作,但没有 C++ 的类型安全std::ostream
性。printf
在使用函数根据用户输入(甚至来自文件的输入)格式化输出的程序中可能会出现问题。例如:
int main()
{
char[] a = {'1', '2', '3', '4'}; // a string that isn't 0-terminated
int i = 50;
printf("%s", a); // will continue printing characters until a 0 is found in memory
printf("%s", i); // will attempt to print a string, but this is actually an integer
}
C++ 具有更强的类型安全性(和一个std::string
类)来帮助防止此类问题。
我自己也在为这个问题而苦苦挣扎。printf 通常更容易用于格式化打印,但 C++ 中的 iostreams 工具具有很大的优势,您可以为对象创建自定义格式化程序。我最终会根据需要在我的代码中使用它们。
使用两者并将它们混合使用的问题在于 printf 和 cout 使用的输出缓冲区不同,因此除非您运行无缓冲或显式刷新输出,否则最终可能会导致输出损坏。
我对 C++ 的主要反对意见是没有类似于 printf 的快速输出格式化工具,因此无法轻松控制整数、十六进制和浮点格式的输出。
Java也有同样的问题;该语言最终得到了 printf。
维基百科在http://en.wikipedia.org/wiki/Printf#C.2B.2B_alternatives_to_sprintf_for_numeric_conversion对此问题进行了很好的讨论。
实际上,对于您的特定示例,您应该询问哪个更可取,puts 或 cout。printf 打印格式化文本,但您只是将纯文本输出到控制台。
对于一般用途,流(iostream,cout 是其中的一部分)更具可扩展性(您可以使用它们打印自己的类型),并且更通用,因为您可以生成函数以打印到任何类型的流,而不仅仅是控制台(或重定向输出)。您也可以使用 printf 创建通用流行为,使用 fprintf 将 FILE* 作为 FILE* 通常不是真正的文件,但这更棘手。
流是“类型安全的”,因为您使用正在打印的类型重载。printf 使用省略号时不是类型安全的,因此如果您输入与格式字符串不匹配的错误参数类型,您可能会得到未定义的结果,但编译器不会抱怨。如果您错过了一个参数或传入了一个错误的参数(例如 %s 的数字并且它仍然将其视为指针),您甚至可能会得到一个 seg-fault / undefined 行为(但如果使用不正确,您可能会使用 cout)。
printf 确实有一些优点:您可以模板化格式字符串,然后为不同的数据重用该格式字符串,即使该数据不在结构中,并且对一个变量使用格式操作不会“粘贴”该格式以供进一步使用,因为您指定每个变量的格式。printf 也被认为是线程安全的,而 cout 实际上不是。
boost 结合了它们各自的优势和 boost::format 库。
是从 C 中借来的printf
,有一些限制。最常见的限制printf
是类型安全,因为它依赖于程序员将格式字符串与参数正确匹配。来自可变参数环境的第二个限制是您不能使用用户定义的类型扩展行为。printf
知道如何打印一组类型,这就是您将得到的全部内容。尽管如此,它可以用于少数几件事,它格式化字符串printf
比使用 c++ 流更快、更简单。
虽然大多数现代编译器能够解决类型安全限制并至少提供警告(编译器可以解析格式字符串并检查调用中提供的参数),但无法克服第二个限制。即使在第一种情况下,编译器也无法真正提供帮助,例如检查空终止 - 但是std::cout
如果您使用它来打印相同的数组,同样的问题也会出现。
另一方面,流(包括std::cout
)可以通过重载std::ostream& operator<<( std::ostream&, type const & )
任何给定的用户定义类型来扩展以处理用户定义的类型type
。它们本身是类型安全的——如果你传入一个没有重载operator<<
的类型,编译器会抱怨。另一方面,它们生成格式化输出更麻烦。
So what should you use? In general I prefer using streams, as overloading operator<<
for my own types is simple and they can be used uniformly with all types.
这两个例子做不同的事情。后者将添加换行符并刷新输出(结果std::endl
)。std::cout
也较慢。除此之外,printf
实现std::cout
相同的目标,您可以选择您喜欢的任何一个。作为偏好,我会std::cout
在 C++ 代码中使用。它更具可读性和安全性。
如果您需要使用std::cout
.
通常,您应该更喜欢 cout,因为它的类型更安全且更通用。printf 不是类型安全的,也不是通用的。您可能喜欢 printf 的唯一原因是速度——从内存中,printf 比 cout 快很多倍。