使用移动语义在构造函数中初始化类成员

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用移动语义在构造函数中初始化类成员相关的知识,希望对你有一定的参考价值。

我正在用C ++学习多线程,我写了一个简单的类,它包含一个私有的std::mutex对象,可以在调用成员函数时进行同步:

#include <mutex>
#include <iostream>

class SynchClass
{
public:
    SynchClass() {}
    void inline SynchronizedInterfaceFunction();    
private:
    std::mutex mMutex;
};

void inline SynchClass::SynchronizedInterfaceFunction()
{
    std::lock_guard<std::mutex> lock(mMutex);

    for (int i = 0; i < 10; i++) 
        std::cout << "thread n: " << std::this_thread::get_id() << " inside function" << std::endl; 

    std::cout << std::endl;
}

现在,我这个函数有一个deleted复制构造函数和复制赋值运算符,因为std :: mutex可以移动但不能复制/分配。

所以我为类提供了一个移动构造函数(它不是由编译器自动生成的):

class SynchClass
    {
    public:
        // ... other members as before
        SynchClass(SynchClass &&rhs) : mMutex(std::move(rhs.mMutex)) {}

    };

但是当我在这行时,编译器抱怨我正在尝试调用std::mutex的已删除的复制构造函数:

In file included from main.cpp:5:0:
SynchClass.h: In constructor 'SynchClass::SynchClass(SynchClass&&)':
SynchClass.h:8:61: error: use of deleted function 'std::mutex::mutex(const std::mutex&)'
  SynchClass(SynchClass &&rhs) : mMutex(std::move(rhs.mMutex)) {}
                                                             ^
In file included from C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++/mutex:43:0,
                 from main.cpp:2:
C:/Program Files/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0/include/c++/bits/std_mutex.h:97:5: note: declared here
     mutex(const mutex&) = delete;

但是我使用std::move将左值转换为右值,因此应该调用std :: mutex的移动构造函数。

我错过了什么?

答案

std::mutex不可复制,不可移动。它没有移动构造函数或赋值。 mutex的图书馆要求:

33.4.3.2互斥体类型[thread.mutex.requirements.mutex] 3互斥锁类型应为DefaultConstructible和Destructible。如果互斥锁类型的对象的初始化失败,则应抛出类型为system_error的异常。互斥锁类型不可复制或移动。

如果你想让你的类移动可构造,那么你需要在某些时候添加另一层间接,例如使用std::unique_ptr<std::mutex>

以上是关于使用移动语义在构造函数中初始化类成员的主要内容,如果未能解决你的问题,请参考以下文章

C++11移动构造函数详解

C++成员初始化列表(构造函数后加冒号:)(用于在构造函数中初始化类成员变量,可以避免使用构造函数体内的赋值语句,可以确保成员变量在对象构造之初就已经被正确初始化,提高代码的性能和可读性)

在构造函数代码之前禁用默认类成员初始化

重载构造函数中的成员初始化

移动语义+对成员成员变量的引用 - 解决方案和命名法?

基类构造函数的派生类成员初始化