在C++中,堆栈对象通常按出现的顺序创建,当它们超出作用域时按相反的顺序销毁。
但是,这只适用于L值,而不是R值,如下面代码on Godbolt所示:
#include <iostream>
class C{
int instanceNo;
public:
C(){
static int instanceCount = 0;
instanceNo = ++instanceCount;
std::cout << "constructed " << instanceNo << "\n";
}
~C(){
std::cout << "destructed " << instanceNo << "\n";
}
};
int main()
{
C one;
C two;
C{}; // three as RValue
C four;
C five;
}
结果:RValue立即被销毁,而不是在main()
结束时。到目前为止,这对我来说很好。
我们有一些C++14代码如下:
std::lock_guard<std::mutex> guard(mutex);
在C++17中,我们可以使用模板参数推导(CTAD)并将代码缩短为
std::lock_guard guard(mutex);
然而,一位同事把它写得更短了:
std::lock_guard{mutex};
在我的理解中,这现在是一个R值。它将在构造时锁定互斥体,这很好。然而,根据上面的演示,它的生命周期立即结束,从而解锁互斥锁并有效地删除保护。
这个结论是正确的吗?这个改变破坏了我们类的线程安全性吗?
1条答案
按热度按时间mo49yndu1#
简而言之,你的分析是100%正确的。
如果你想专门测试
std::lock_guard
:它只需要一个实现.lock()
和.unlock()
的类,所以你可以创建一个只打印调试输出的伪锁:这将打印:
如果将该行更改为
std::lock_guard guard{mtx};
,则输出将更改为: