我在类中声明互斥锁时遇到问题,每当我尝试实例化类时,出现错误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_);
}
答案 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
,它必须是CopyInsertable或 - 如果参数是rvalue(例如临时) - MoveInsertable(我相信任何CopyInsertable类型也是MoveInsertable)emplace_back
,必须是MoveInsertable 和 EmplaceConstructible。 基本上,这意味着,当您想要使用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
。