在Qt
中,我们常用 qDebug()
打印输出一些调试信息,也因为他的外观像极了一个函数,所以我们很自然的联想或者认为它就是一个函数。
如下的打印输出:
qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << i << s_num << Qt::endl;
what ? qDebug()
是一个函数啊,他后面为啥直接接了<<
符号啊?什么鬼~
哦,soeasy。qDebug()
他确实是一个函数,但是可不是如外表这样普通,他是一个级联函数。(所以,我标题党了)。函数返回了一个QDebug
对象,对象如果重载了<<
操作符,这不是完全有可能的么。
#define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug
#define qInfo QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).info
#define qWarning QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).warning
#define qCritical QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).critical
#define qFatal QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).fatal
qDebug
显然是一个宏,qDebug()
才是一个宏函数。
qDebug() ==> QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug()
看到这儿,哦,原来是构造了一个MessageLogger
的对象然后调用对象的成员函数 debug()
函数,并返回了一个QDebug
的对象。
class Q_CORE_EXPORT QMessageLogger
{
Q_DISABLE_COPY(QMessageLogger)
public:
Q_DECL_CONSTEXPR QMessageLogger() : context() {}
Q_DECL_CONSTEXPR QMessageLogger(const char *file, int line, const char *function)
: context(file, line, function, "default") {}
Q_DECL_CONSTEXPR QMessageLogger(const char *file, int line, const char *function, const char *category)
: context(file, line, function, category) {}
....
QDebug debug() const;
QDebug debug(const QLoggingCategory &cat) const;
QDebug debug(CategoryFunction catFunc) const;
QDebug info() const;
QDebug info(const QLoggingCategory &cat) const;
QDebug info(CategoryFunction catFunc) const;
QDebug warning() const;
QDebug warning(const QLoggingCategory &cat) const;
QDebug warning(CategoryFunction catFunc) const;
QDebug critical() const;
QDebug critical(const QLoggingCategory &cat) const;
QDebug critical(CategoryFunction catFunc) const;
QNoDebug noDebug() const noexcept;
};
那么我们再来看:
qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << i << "s_num++"<< s_num;
我们说是QDebug
的操作符重载。我也是有理由的:
inline QDebug &operator<<(QChar t) { putUcs4(t.unicode()); return maybeSpace(); }
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
#ifdef Q_COMPILER_UNICODE_STRINGS
inline QDebug &operator<<(char16_t t) { return *this << QChar(ushort(t)); }
inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
#endif
inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
确实重载了,而且返回了一个QDebug
自身的reference
对象.
inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
哦豁,难怪qDebug()
可以级联使用 <<
打印输出字符串的啦。
qDebug()
、std::cout
和printf()
的不完全比较在Qt中,qDebug()、printf()和std::cout都是用于输出调试信息的函数。它们在性能开销上有一些区别。
不完全统计结果:
printf
> std::cout
> qDebug()
既然性能吊车尾,那为啥还用它。首先我们这个不完全统计的结果,是基于都循环打印输出100,0000万条数据的时间比较,平时小的程序偶尔输出个几条,其实没有太大影响的。而且qDebug()
相比std::cout
和printf()
,它还有自身的优点。
qDebug()
:qDebug()
是Qt框架提供的用于输出调试信息的函数,它可以输出丰富的调试信息,并且可以通过Qt的日志系统进行更灵活的控制。qDebug()
输出会被禁用,因此在发布版本中不会产生额外的性能开销。使用 #define QT_NO_DEBUG_OUTPUT
可以禁用qDebug()
输出2.printf()
:
printf()
是C语言中用于输出格式化字符串的函数,它在标准输出流中输出信息。printf()
通常不推荐在Qt应用程序中使用,因为它不利于与Qt的其他特性(如国际化、本地化等)集成。std::cout
:std::cout
是C++标准库中用于输出信息到标准输出流的对象。printf()
类似,std::cout
在Qt应用程序中也不利于与Qt的其他特性集成。总体而言,qDebug()
在发布版本中会被禁用,因此不会产生额外的性能开销。而printf()
和std::cout
在Qt应用程序中不利于与Qt的特性集成,且在一些情况下可能会产生较大的性能开销。因此,在Qt应用程序中,建议使用qDebug()
来输出调试信息。
qDebug()
是一个通过宏简化的级联函数
,这在此告诉我们,适当的使用宏,可以简化我们的代码,使他变得更优雅;不适当的简化,可能等同于被化妆到她亲妈也不认得~😓