试图引用已删除的函数、具有互斥成员的结构
Attempting to reference a deleted function, structure with mutex member
这是我的问题。
我有这样的结构。
struct threadInfo
{
std::condition_variable cv;
std::mutex m;
int priorityLevel;
};
构建代码时出现此错误
Error C2280 threadInfo::threadInfo(const threadInfo &)
: attempting
to reference a deleted function PriorityListMutex
根据我的理解,这意味着 threadInfo
的构造函数被调用并且它试图复制 mutex
这是不可能的。
我对 C++ 没有太多经验,虽然我有点了解正在发生的事情,但我不确定如何尝试解决这个问题。任何帮助都会很棒!
这里是使用ThreadInfo的代码
threadInfo info;
info.priorityLevel = priority;
priorityListMutex.lock();
for (std::list<threadInfo>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < info.priorityLevel)
{
threadList.insert(it, info);
break;
}
else if (it == threadList.end())
{
threadList.push_back(info);
break;
}
}
priorityListMutex.unlock();
std::unique_lock<std::mutex> lock(info.m);
info.cv.wait(lock);
我猜结构正在那里的某个地方被复制,但我完全不知道在哪里。
在标准 C++ 库中,class与线程相关的元素,如互斥量,没有复制构造函数。
当一个赋值涉及两个对象时,比如
Class b(10);
Class a = b;
在第二行,我们尝试创建一个从另一个对象初始化的对象。这使得编译器寻找一个复制构造函数,一个专门为此目的开发的构造函数。
由于具有两个相同的互斥锁副本并不好,库不会将这种方法用于与线程相关的 classes。
通常编译器会创建默认的复制构造函数以备不时之需,但是当 class 这种类型的 属性 时它不能这样做,所以它给你和错误。
要解决这个问题,您必须显式定义一个复制构造函数并手动处理。当心,你应该记住,与线程相关的东西,如 mutex 和 cv 不应该存在超过一个副本。
mutex的复制构造函数被显式删除。但是,如果您正在做的是移动而不是复制(例如,您不需要 threadInfo 对象的旧值),那么您不能复制互斥锁,那么您可以使用 std::move
移动互斥锁并编写一个为您的 threadInfo 对象移动构造函数。
但是,移动构造函数可能导致难以发现错误,因此我不推荐这样做。更直接的方法是将 "info" 对象包装在一个指针中并使用它。您可以这样实现:
auto info = std::make_shared<threadInfo>{};
info->priorityLevel = priority;
priorityListMutex.lock();
for (std::list<std::shared_ptr<threadInfo>>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < info->priorityLevel)
{
threadList.insert(it, info);
break;
}
else if (it == threadList.end())
{
threadList.push_back(info);
break;
}
}
priorityListMutex.unlock();
std::unique_lock<std::mutex> lock(info.m);
info->cv.wait(lock);
但是请注意,在这种情况下,我使用的是 shared_ptr,这是 "easiest" 的方法,因为它不会破坏任何东西,但可能不希望你想要做,你最有可能想做的,是给你的信息对象的 'threadList' 对象所有权。在这种情况下,您可以将其声明为 unique_ptr:
auto info = std::make_uniq<threadInfo>{};
and move it into the threadList:
threadList.insert(it, std::move(info));
您可以通过避免复制并将结构直接放置在列表中来解决您的问题。不过,这确实需要自定义构造函数。我已将您的代码示例缩短为仅显示放置部分:
#include <mutex>
#include <condition_variable>
#include <list>
struct threadInfo
{
explicit threadInfo(int prio) : priorityLevel(prio) {}
std::condition_variable cv;
std::mutex m;
int priorityLevel;
};
int main()
{
std::list<threadInfo> threadList;
int priorityLevel = 0;
for (std::list<threadInfo>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < priorityLevel)
{
threadList.emplace(it, priorityLevel);
break;
}
else if (it == threadList.end())
{
threadList.emplace_back(priorityLevel);
break;
}
}
return 0;
}
这是我的问题。
我有这样的结构。
struct threadInfo
{
std::condition_variable cv;
std::mutex m;
int priorityLevel;
};
构建代码时出现此错误
Error C2280
threadInfo::threadInfo(const threadInfo &)
: attempting to reference a deleted functionPriorityListMutex
根据我的理解,这意味着 threadInfo
的构造函数被调用并且它试图复制 mutex
这是不可能的。
我对 C++ 没有太多经验,虽然我有点了解正在发生的事情,但我不确定如何尝试解决这个问题。任何帮助都会很棒!
这里是使用ThreadInfo的代码
threadInfo info;
info.priorityLevel = priority;
priorityListMutex.lock();
for (std::list<threadInfo>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < info.priorityLevel)
{
threadList.insert(it, info);
break;
}
else if (it == threadList.end())
{
threadList.push_back(info);
break;
}
}
priorityListMutex.unlock();
std::unique_lock<std::mutex> lock(info.m);
info.cv.wait(lock);
我猜结构正在那里的某个地方被复制,但我完全不知道在哪里。
在标准 C++ 库中,class与线程相关的元素,如互斥量,没有复制构造函数。
当一个赋值涉及两个对象时,比如
Class b(10);
Class a = b;
在第二行,我们尝试创建一个从另一个对象初始化的对象。这使得编译器寻找一个复制构造函数,一个专门为此目的开发的构造函数。
由于具有两个相同的互斥锁副本并不好,库不会将这种方法用于与线程相关的 classes。
通常编译器会创建默认的复制构造函数以备不时之需,但是当 class 这种类型的 属性 时它不能这样做,所以它给你和错误。
要解决这个问题,您必须显式定义一个复制构造函数并手动处理。当心,你应该记住,与线程相关的东西,如 mutex 和 cv 不应该存在超过一个副本。
mutex的复制构造函数被显式删除。但是,如果您正在做的是移动而不是复制(例如,您不需要 threadInfo 对象的旧值),那么您不能复制互斥锁,那么您可以使用 std::move
移动互斥锁并编写一个为您的 threadInfo 对象移动构造函数。
但是,移动构造函数可能导致难以发现错误,因此我不推荐这样做。更直接的方法是将 "info" 对象包装在一个指针中并使用它。您可以这样实现:
auto info = std::make_shared<threadInfo>{};
info->priorityLevel = priority;
priorityListMutex.lock();
for (std::list<std::shared_ptr<threadInfo>>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < info->priorityLevel)
{
threadList.insert(it, info);
break;
}
else if (it == threadList.end())
{
threadList.push_back(info);
break;
}
}
priorityListMutex.unlock();
std::unique_lock<std::mutex> lock(info.m);
info->cv.wait(lock);
但是请注意,在这种情况下,我使用的是 shared_ptr,这是 "easiest" 的方法,因为它不会破坏任何东西,但可能不希望你想要做,你最有可能想做的,是给你的信息对象的 'threadList' 对象所有权。在这种情况下,您可以将其声明为 unique_ptr:
auto info = std::make_uniq<threadInfo>{};
and move it into the threadList:
threadList.insert(it, std::move(info));
您可以通过避免复制并将结构直接放置在列表中来解决您的问题。不过,这确实需要自定义构造函数。我已将您的代码示例缩短为仅显示放置部分:
#include <mutex>
#include <condition_variable>
#include <list>
struct threadInfo
{
explicit threadInfo(int prio) : priorityLevel(prio) {}
std::condition_variable cv;
std::mutex m;
int priorityLevel;
};
int main()
{
std::list<threadInfo> threadList;
int priorityLevel = 0;
for (std::list<threadInfo>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < priorityLevel)
{
threadList.emplace(it, priorityLevel);
break;
}
else if (it == threadList.end())
{
threadList.emplace_back(priorityLevel);
break;
}
}
return 0;
}