我有一个MyClass的QList。从列表中追加和删除项目很少见,并且由常用列表互斥锁控制。 MyClass包含几个子结构和个人QReadWriteLock:
MyClass{
private:
Substructure substructure;
QReadWriteLock rwlElem;
}
我把储物柜放在这样的加速器中:
Substructure MyClass::getSub(){
QReadLocker lock(&rwlElem);
return substructure;
}
我希望能够安全地返回子结构的副本。我在制作者中所做的一样。这是一个很好的做法,使用这样的储物柜?首先会发生什么:复制下部结构或破坏储物柜?
答案 0 :(得分:0)
我首先回答你的上一个问题:
首先发生什么:复制子结构的构造或破坏储物柜?
TL; DR:复制构造在破坏所有局部变量之前发生。
此处已在stackoverflow上多次询问此问题,请参阅here,here和here。
CWG 1885已将更精确的措辞应用于C ++ 14标准:
N4606§6.6.3[stmt.return] / 3
调用结果的复制初始化在由return语句的操作数建立的完整表达式结束时临时销毁之前被排序,然后,在销毁之前被排序包含return语句的块的局部变量(6.6)。
我有一个MyClass的QList。从列表中追加和删除项目很少见,并且由常用列表互斥锁控制。 MyClass包含几个子结构和个人QReadWriteLock
要锁定两个互斥锁会使您容易出现死锁。但是,您可以遵循以下两条准则之一来避免这种情况:
MyClass
实例的读/写互斥锁之前的列表。我在制作者中所做的一样。这是一个很好的做法,使用这样的储物柜?
假设您在setter中使用了QWriteLocker
,这应该没问题(从某种意义上说它不会导致未定义的行为)。但是你必须注意你的界面真正在说什么。例如,当您对类型为mc
的实例MyClass
执行此类操作时:
Substructure s = mc.getSub();
if(s == anotherSubstructure)
mc.doSomething();
当执行上述代码的线程将s
与anotherSubstructure
进行比较时,另一个线程可能会更改substructure
内的实际mc
,此更改不是' t对前一个线程可见(因为它有自己的substructure
副本。)
关键是,当您执行Substructure s = mc.getSub();
时,您唯一知道的是mc
的子结构在某个时间点等于s
< / strong>,一旦您在getSub
函数中释放锁定,此值可能会更改。
在上面的例子中,doSomething()
不能假设mc
的子结构的值仍然等于anotherSubstructure
。您可能需要在自己的函数中对需要原子化的操作进行分组(使用锁可以确保在上述情况下值不会发生变化)。