【问题标题】:Attempting to reference a deleted function when using a mutex尝试在使用互斥锁时引用已删除的函数
【发布时间】:2015-02-03 23:53:19
【问题描述】:

我在处理一个项目时遇到了一个奇怪的错误。我创建了一个超级简单的示例来重新创建错误。

我创建了一个类。我想在这个类中做的是为我的类提供一种“getter”函数来填充struct 的值。在主应用程序中,用户将实例化这个struct,将它传递给一个成员函数,并能够在返回时读取struct 中的值。由于实际类的设计,这必须在单独的线程中发生。这是我所拥有的:

myClass.h:

#ifndef __MY_CLASS_H__
#define __MY_CLASS_H__

#include <mutex>

class myClass {
public:
    struct my_struct_s {
        int field1;
        short field2;
    };

    int get_data(my_struct_s & my_struct);

private:

};

#endif /* __MY_CLASS_H__ */

myClass.cpp:

#include "myClass.h"

int myClass::get_data(struct my_struct_s & my_struct)
{
    int var1 = 5;
    char var2 = 2;

    my_struct.field1 = var1;
    my_struct.field2 = var2;

    return 0;
}

Main.cpp:

#include "myClass.h"
#include <iostream>
#include <thread>
#include <Windows.h>

bool thread_running;
std::thread thread;

void run_thread(myClass & lmyClass)
{
    myClass::my_struct_s my_struct;

    while (thread_running) {
        lmyClass.get_data(my_struct);

        std::cout << my_struct.field1 << std::endl;
        std::cout << my_struct.field2 << std::endl;

        Sleep(100);
    }
}

int main(int argc, char *argv[])
{
    myClass lmyClass; 

    thread_running = true;
    thread = std::thread(run_thread, lmyClass);

    Sleep(1000);
    thread_running = false;

    if (thread.joinable()) {
        thread.join();
    }

    getchar();

    return 0;
}

它按预期工作。但是,由于类的异步特性,我需要互斥锁来保护在类内不同线程中处理的数据。

如果我将std::mutext 添加为我班级的私人成员,我会在尝试运行代码时收到以下信息:

Error 1 error C2280: 'std::mutex::mutex(const std::mutex &amp;)' : attempting to reference a deleted function ...

1) 我正在尝试了解我收到此错误的原因。

2) (这部分更多地基于意见),鉴于信息,这种填写公共结构的“getter”方式是不是一个好的设计?有没有更好的方法?

【问题讨论】:

  • 请显示尝试使用std::mutex 时失败的实际代码。
  • 如前所述,std::mutex 不可复制。而且它也不能移动。但是,如果您愿意,可以将 unique_ptr 设置为互斥体。在此期间,我会将 thread_running 变成 atomic
  • @SeverinPappadeux 如果我改为在 Main.cpp 中实例化 lmyClass 全局,并在我的线程中访问此对象而不是将其作为参数传递,它就可以工作。哪种解决方案更好?
  • 不确定我是否理解:如果它是全局的,那么它更像是单例,但如果你在一个线程中访问它,那么为什么还要使用互斥锁/锁定呢?你能发布/发送代码吗?在我们做的时候,你可能想用 std::this_thread::yield() 替换 Sleep(100),如果无事可做,自愿放弃时间片
  • 在这种情况下,(阅读器线程和处理线程)您可能需要使用条件变量。作为一个简单的例子(尽管我会将其更改为使用 atomic),en.cppreference.com/w/cpp/thread/condition_variable 或在此处讨论:stackoverflow.com/questions/13371020/…

标签: c++ multithreading c++11 struct


【解决方案1】:

myclass 中没有复制构造函数,因此编译器为其提供了默认的复制构造函数。这将尝试复制所有成员,包括您的std::mutex不可复制。正如编译器错误所说,它被标记为已删除。

你需要定义自己的拷贝构造函数;您很可能希望它获取存储在正在复制的实例中的互斥锁,然后将其所有其他成员复制到新实例中。

【讨论】:

  • 那么出于好奇,这意味着所有需要 std:mutex 作为成员的类都需要用户定义的复制构造函数?
  • @Kam:仅当您尝试调用类的复制构造函数时。
  • 嗯,如果您希望每个副本都有自己的互斥体实例怎么办?这有可能吗?
  • @Kam:如果你的类有一个std::mutex 成员,每个实例都会有它自己不同的互斥体。
【解决方案2】:

动态地而不是静态地声明您的互斥锁。

在您的 myClass 类头中,将互斥锁声明为指针,如下所示:

mutex * mtx;

并在您的构造函数中初始化互斥锁,调用他的构造函数:

mtx = new std::mutex();

【讨论】:

    猜你喜欢
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 2020-05-02
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    相关资源
    最近更新 更多