C ++类中的C2280互斥错误

时间:2015-07-16 22:16:51

标签: c++ class mutex

我在类中声明互斥锁时遇到问题,每当我尝试实例化类时,出现错误C2280。我的项目也创造了餐饮哲学家问题的模拟。

声明:

class Fork
{

public:

struct _position
{
    float x;
    float y;
};

Fork();
Fork(int num_phil_, int new_index_);
_position ReturnWorkPosition(){ _position return_position_; /*position_mutex_.lock();*/ return_position_ = work_position_; 
                                    /*position_mutex_.unlock();*/ return return_position_; };
float ReturnRotation(){ return rotation_; };

void CalculateWorkPosition(int master_index_);
void ResetWorkPosition(){ /*position_mutex_.lock();*/ work_position_ = orig_position_; /*position_mutex_.unlock();*/ };
void TakeOwnership(int master_index_);
void RelinquishOwnership();

private:

int index_;
int num_philosophers_;
float rotation_;

_position orig_position_;
_position work_position_;

//std::mutex master_mutex_;
//std::mutex position_mutex_;
};

实例化:

for (int i = 0; i < num_philosophers_; i++)
{
    Fork temp_fork_(num_philosophers_, i);
    fork_.push_back(temp_fork_);
}

编辑::新声明:

class Fork
{

public:

Fork();
Fork(int num_phil_, int new_index_);

Fork(Fork const&) = delete;
Fork& operator=(Fork const&) = delete;

struct _position
{
    float x;
    float y;
};

_position ReturnWorkPosition(){ _position return_position_; /*position_mutex_.lock();*/ return_position_ = work_position_; 
                                    /*position_mutex_.unlock();*/ return return_position_; };
float ReturnRotation(){ return rotation_; };

void CalculateWorkPosition(int master_index_);
void ResetWorkPosition(){ /*position_mutex_.lock();*/ work_position_ = orig_position_; /*position_mutex_.unlock();*/ };
void TakeOwnership(int master_index_);
void RelinquishOwnership();

private:

int index_;
int num_philosophers_;
float rotation_;

_position orig_position_;
_position work_position_;

//std::mutex master_mutex_;
//std::mutex position_mutex_;
};

错误讯息:

Error   18  error C2280: 'Fork &Fork::operator =(const Fork &)' : attempting to reference a deleted function    c:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility 2045    1   Lab3e

Error   13  error C2280: 'Fork::Fork(const Fork &)' : attempting to reference a deleted function    c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 600 1   Lab3e

新实例化:

for (int i = 0; i < num_philosophers_; i++)
{
    Fork temp_fork_(num_philosophers_, i);
    fork_.emplace_back(temp_fork_);
}

2 个答案:

答案 0 :(得分:2)

您需要删除复制构造函数和复制赋值运算符。您无法复制.ready()因此无法复制班级实例,只能构建或移动班级。

std::mutex

错误告诉您您正在尝试引用已删除的函数,即复制构造函数,因为Fork(Fork const&) = delete; Fork& operator=(Fork const&) = delete; 正在尝试复制您的push_back。相反,我会使用temp_fork_来就地创建emplace_back

Fork

或者

for (int i = 0; i < num_philosophers_; i++)
{
    fork_.emplace_back(num_philosophers_, i);
}

旁注
您可以使用std::lock_guard代替手动锁定和解锁for (int i = 0; i < num_philosophers_; i++) { Fork temp_fork_(num_philosophers_, i); fork_.push_back(std::move(temp_fork_)); } ,{{3}}是设置为通过RAII锁定/解锁互斥锁的类

std::mutex

答案 1 :(得分:0)

正如@sbabbi在对@CoryKramer的回答的评论中指出的那样,问题是你的类需要有一个副本或移动构造函数,因为它的一些成员(互斥体)没有自己的一个,编译器隐式删除(我的术语)Fork的那些特殊函数。因此,您必须自己为Fork实现至少一个或使用指针(见下文)。

<强>解释

为了能够存放在容器中,您的班级T必须满足某些要求。对于std::vector和直到c ++ 11,T必须是CopyAssignable和CopyConstructible。但是,从c ++ 11开始,确切的要求取决于你实际尝试调用的函数(T总是必须是可擦除的。)

基本上,这意味着,当您想要使用push_back时,您的类型必须具有复制构造函数,即使您使用emplace_back,您仍然至少需要一个移动构造函数。理性的是,如果push / emplace_back导致重新分配,则必须将元素从旧内存区域移动到新内存区域。

现在复制或移动mutex没有多大意义,这就是为什么它没有任何这些成员函数(它们被标准声明为已删除)。因此,您的编译器也不会为Fork类隐式定义那些复制/移动构造函数,而是隐式删除它们,然后向您提供尝试使用已删除函数的错误。

可能的解决方案

您可以定义自己的复制构造函数,如下所示:

Fork::Fork(const Fork& other) {
    /* potentially locking a mutex of other, 
       which would have to be declared mutable */
    index_            =other.index_;
    num_philosophers_ =other.num_philosophers_;
    rotation_         =other.rotation_;
    orig_position_    =other.orig_position_;
    work_position_    =other.work_position_;
}

问题是在(多线程)程序的上下文中可能很难定义复制构造函数的正确语义。如果你只需要它来将Forks插入到一个向量中,那么在你的程序的进一步执行期间不会修改它,你应该可以忽略互斥锁。

但是,最好将指针存储到Fork

for (int i = 0; i < num_philosophers_; i++) {      
    fork_.push_back(std::unique_ptr<Fork>(new Fork(num_philosophers_, i)));
    //or if your compiler is c++14 compatible:
    fork_.push_back(std::make_unique<Fork>(num_philosophers_, i));      
}

第三,您可以使用其他容器,例如std::list而不是vector(您仍然必须使用emplace_back代替push_back