首先,我有50%的概率跟你写的一样;有50%的概率会定义空的ByteArray. 取决于开发时的进度压力,或者当时着重解决的问题.
const QByteArray fkEmpty; // 模拟常见的 static const Vec3& Vec::Zero();
double funcA(..., const char *path) {
...
return funcB(..., fkEmpty);
}
其次,我看了QByteArray的源码,确实没懂为啥会多线程下会锁。
代码来自:
https://code.woboq.org/qt5/qtbase/src/corelib/text/qbytearray.h.html#_ZN10QByteArrayC1Ev我分析一共6步,见所贴代码的注释:
// 1 QByteArray 的空构,调用模板类 QTypedArrayData<char> 的sharedNUll
// 2 sharedNull()的实现,调用了基类QArrayData的同名函数
// 3 基类的实现,只是一个简单的 const_cast, 取成员变量数组(D2)的指针
// 4 D2的初始化,调用了宏 Q_REFCOUNT_INITIALIZE_STATIC, 用于初始化成员变量D1
// 【我认为只会初始化一次,在Dll加载时】
// 5 计数器D1,加减时会有加锁开销。【我认为这是你说的那把锁】
// 6 宏的定义与展开. 展开后,相当于 使用{(0)} 来初始化 QBasicAtomicInt.
还请指点一下,构造空的QBtyeArray时:
1 哪里导致了每次加锁、 进而影响了效率呢?
2 另外你说,“你不业余的话,解释解释为啥多线程【才】有性能问题啊?”,“才”的言外之意,单线程不会?
class Q_CORE_EXPORT QByteArray {
private:
typedef QTypedArrayData<char> Data;
...
// 1 QByteArray 的空构,调用模板类 QTypedArrayData<char> 的sharedNUll
inline QByteArray::QByteArray() noexcept : d(Data::sharedNull()) { }
}
// 2 sharedNull()的实现,调用了基类QArrayData的同名函数
static QTypedArrayData *sharedNull() noexcept {
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
return static_cast<QTypedArrayData *>(QArrayData::sharedNull());
}
struct Q_CORE_EXPORT QArrayData {
QtPrivate::RefCount ref; // D1 用于计数的类, 其中含锁
int size;
uint alloc : 31;
uint capacityReserved : 1;
...
static const QArrayData shared_null[2]; // D2 一个静态数组,我认为只会初始化一次.
// 3 基类的实现,只是一个简单的 const_cast, 取成员变量数组的指针
static QArrayData *sharedNull() noexcept { return const_cast<QArrayData*>(shared_null); }
};
// 4 D2的初始化,调用了宏 Q_REFCOUNT_INITIALIZE_STATIC, 用于初始化成员变量D1
// 【我认为只会初始化一次,在Dll加载时】
const QArrayData QArrayData::shared_null[2] = {
{ Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared null
/* zero initialized terminator */};
class RefCount {
...
QBasicAtomicInt atomic; // 5 计数器D1,加减时会有加锁开销。【我认为这是你说的那把锁】
}
// 6 宏的定义与展开 展开后,相当于 使用{(0)} 来初始化 QBasicAtomicInt.
#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }
#ifndef Q_BASIC_ATOMIC_INITIALIZER
# define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }
#endif
【 在 jjfz 的大作中提到: 】
: 你不业余的话,解释解释为啥多线程才有性能问题啊?
: 这里传不传引用,不是多线程性能瓶颈,实际上也用了引用
: extern double funcB(..., const QByteArray &path)
: ...................
--
修改:DoorWay FROM 61.185.187.*
FROM 61.185.187.*