看起来 C++ 编译器允许我在 C++ 头文件中#define
QStringLiterals。像这样的东西:
// foo.h
#ifndef FOO_H
#define FOO_H
#define BAR QStringLiteral("bar")
#endif
目标是在包含 foo.h
的不同 .cpp 文件中使用(复制)BAR
,这样我就可以避免多次键入 QStringLiteral (“栏”)
。
但是:
- 安全吗? (我听说 QStringLiteral 会导致崩溃)
- 它有效率吗? (即字符串是否只分配一次?)
最佳答案
不要那样做。
关于您的问题:
- 安全吗? (我听说 QStringLiteral 会导致崩溃)
问题是为什么 QStringLiteral 可能会崩溃,答案与库和插件卸载有关。 QStringLiteral 创建一个引用静态有效负载(QString 自己的数据和实际字符串)的 QString。如果这个 QString 在库 A 中创建,传递给库 B,然后库 A 被卸载,B 就会留下一个危险的悬挂指针。 Qt 对此无能为力。
- 它有效率吗? (即字符串是否只分配一次?)
完全没有:
- 您最终会在使用它的任何地方出现字符串文字数据。这可能会激增数据大小,或者对链接器施加更大的压力以跨多个 TU 合并相同的字符串文字数据。
- 由于 QStringLiteral 扩展为 lambda 表达式(...给定体面的编译器),您向编译器施加压力,使其在每次宏出现时解析并为 lambda 表达式生成代码
- 由于每个 lambda 必须传递一个唯一类型的对象,因此编译器无法轻易合并多个宏扩展——即使在同一个 TU 中。直到最近,优化器才开始折叠相同的二进制代码。
解决方案:写一个外联函数:
// foo.h
#ifndef FOO_H
#define FOO_H
QString bar();
#endif
和
// foo.cpp
#include "foo.h"
QString bar() {
return QStringLiteral("bar");
}
关于c++ - 我可以在头文件中#define QStringLiterals 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36424321/