今天在網路上看到一篇討論C++語法的文章,討論一般在取用需使用lock物件鎖定保護的資料的相關可能作法。以下先將文章中提到的基本方式,以及其中一種方式整理成完成的程式碼列示如下,至於這裏所說的完整程式碼是指可以正常編譯的。因為原始文章中只提供程式碼片段而已。
#include <mutex>
class Widget{
};
class TestCase{
// Assume we have these member variables
std::mutex m_mutex;
Widget m_widget;
public:
void Test01(){
// Get a copy of the widget
Widget widget;
{
auto guard = std::lock_guard(m_mutex);
widget = m_widget;
}
}
void Test02(){
// Get a copy of the widget
Widget widget = [&] {
auto guard = std::lock_guard(m_mutex);
return m_widget;
}();
}
};
int main(){
TestCase t1;
t1.Test01();
t1.Test02();
return 0;
}
程式碼範例中的TestCase::Test01()就是一般最常用的方式。首先會先宣告一個Widget物件,再進行Lock,並於Lock區段中將資料複製一份出來。在這段基本的用法中,因為一開始先宣告了一個Widget物件,所以default constructor就會被呼叫,如果這個物件的default constructor裏要做的事不少的話,那這段就會被浪費掉了。因為最後這個物件還是會被另一個物件內容所取代。
所以文章作者的想法就是想看看是否有其它方式可以省掉這個執行default consturctor的部份。作者提供的第一種方式就是用lambda函式在Lock下取出及回傳物件的內容,而呼叫函式的部份就用一個物件來接收(參考TestCase::Test02這個函式)。在這裏則是使用了編譯器最佳化的RVO(Return Value Optimization)方式,在TestCase::Test01函式中的傳回值直接就是套用到函式外等待接收的物件上,這樣可以省去一次的default constructor的呼叫。
至於其它還有幾種可替代的方式,就請大家再自行參考原始文章了。