Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading std::thread的作用域线程包装器_Multithreading_C++11_Move Semantics_Clang++_Stdthread - Fatal编程技术网

Multithreading std::thread的作用域线程包装器

Multithreading std::thread的作用域线程包装器,multithreading,c++11,move-semantics,clang++,stdthread,Multithreading,C++11,Move Semantics,Clang++,Stdthread,我正在尝试创建一个作用域线程 #include <iostream> #include <thread> class ScopedThread { public: template< class Function, class... Args> explicit ScopedThread( int id, Function&& f, Args&&... args) : m_thread( st

我正在尝试创建一个作用域线程

#include <iostream>
#include <thread>

class ScopedThread {
 public:
    template< class Function, class... Args>
    explicit ScopedThread( int id, Function&& f, Args&&... args)
        : m_thread( std::ref(f), std::forward<Args>(args)...)
        , id(std::move(id)) {
    }



    int getId() const { return id; }

    ~ScopedThread() { m_thread.join(); }
 private:
    std::thread m_thread;
    int id;

};

class Worker {
 public:
    Worker(int id): thd(id, &Worker::work, this) { }

    void work() {
       for( int i = 0; i < 10; i++)
        std::cout << "I am working" << std::endl;
    }


 private:
    ScopedThread thd;
};

int main() {
    Worker(1);
    Worker(2);
    Worker(3);
    Worker(4);
}
#包括
#包括
类作用域线程{
公众:
模板<类函数,类…参数>
显式ScopedThread(int-id、函数和函数、参数和…参数)
:m_线程(标准::参考(f),标准::正向(参数)…)
,id(标准::移动(id)){
}
int getId()常量{return id;}
~ScopedThread(){m_thread.join();}
私人:
标准:螺纹m_螺纹;
int-id;
};
班主任{
公众:
Worker(intid):thd(id,&Worker::work,this){}
无效工作(){
对于(int i=0;i<10;i++)

std::cout在
ScopedThread
的实现中有几个问题

  • 不需要单独处理
    函数和&f
    。只需将其作为
    args…
    包的一部分处理即可

  • 无需移动
    id

    template< class... Args>
    explicit ScopedThread( int id, Args&&... args)
        : m_thread( std::forward<Args>(args)...)
        , id(id) {
    }
    
  • 应用这些更改


    罪魁祸首是
    std::ref(f)
    -您正在创建一个临时
    reference\u包装
    ,并将其传递给
    std::thread
    的构造函数,该构造函数使用
    std::invoke
    调用它

    根据
    g++
    和未定义的行为准则:

    /usr/local/gcc-head/include/c++/7.0.1/bits/invoke.h:73:46:

    运行时错误:对的未对齐地址0x7fff939ec8d3的成员调用 键入“struct Worker”,需要8字节对齐

    问题是,您正在使用
    std::ref(f)
    创建对临时工的引用,其中临时工是
    &Worker::work


    我给任何研究该主题的人5美分

    我清理了代码并实现了删除的构造函数:

    class ScopedThread{
    public:
        template<class ...Args>
        explicit ScopedThread(Args &&...args) : thread_(std::forward<Args>(args)...){}
    
        ScopedThread(ScopedThread &&other){
            thread_ = std::move(other.thread_);
        }
    
        ScopedThread &operator=(ScopedThread &&other){
            thread_ = std::move(other.thread_);
            return *this;
        }
    
        std::thread &operator*(){
            return thread_;
        }
    
        std::thread const &operator*() const{
            return thread_;
        }
    
        std::thread *operator->(){
            return & operator*();
        }
    
        std::thread const *operator->() const{
            return & operator*();
        }
    
        auto get_id() const{
            return thread_.get_id();
        }
    
        auto join(){
            if (thread_.joinable())
                thread_.join();
        }
    
        ~ScopedThread(){
            join();
        }
    
    private:
        std::thread thread_;
    };
    
    类作用域线程{
    公众:
    模板
    显式作用域线程(Args&&…Args):线程(std::forward(Args)…{}
    ScopedThread(ScopedThread&&other){
    线程=标准::移动(其他线程);
    }
    ScopedThread&operator=(ScopedThread&other){
    线程=标准::移动(其他线程);
    归还*这个;
    }
    标准::线程和运算符*(){
    返回线程;
    }
    std::线程常量和运算符*()常量{
    返回线程;
    }
    标准::线程*运算符->(){
    返回&运算符*();
    }
    std::线程常量*运算符->()常量{
    返回&运算符*();
    }
    自动获取id()常量{
    返回线程。获取线程id();
    }
    自动联接(){
    if(线程可接合())
    螺纹连接();
    }
    ~ScopedThread(){
    join();
    }
    私人:
    标准:螺纹螺纹;
    };
    
    是否使用-pthread构建?是的,我想如果不使用-pthread,错误将非常详细。例如,启用多线程以使用std::thread:Operation not permitteddwell,您确定您的运行方式与粘贴在此处的完全相同吗?因为这对我来说在gcc 4.8.4Ya上也适用,在我的情况下,它在gcc中也适用,而不是在clangedited the question中实际上,似乎是使用std::forward(f)而不是std::ref。你能解释一下为什么这会导致崩溃吗?@MK.刚刚添加了一个解释。我认为问题在于
    std::ref(f)
    正在创建一个
    reference\u包装器
    ,然后将它传递给
    std::thread::thread
    进行调用。
    if(m_thread.joinable())m_thread.join()
    :在这种情况下线程什么时候可以被销毁?成员不是在离开析构函数时被销毁的吗?@AndyT:我假设移动操作最终会为
    ScopedThread
    实现。在这种情况下,从
    std::thread
    实例移动可能会使其不可连接。@AndyT:我将其视为“所有权转移”-想想
    独特的\u ptr
    ~ScopedThread() { if(m_thread.joinable()) m_thread.join(); }
    
    class ScopedThread{
    public:
        template<class ...Args>
        explicit ScopedThread(Args &&...args) : thread_(std::forward<Args>(args)...){}
    
        ScopedThread(ScopedThread &&other){
            thread_ = std::move(other.thread_);
        }
    
        ScopedThread &operator=(ScopedThread &&other){
            thread_ = std::move(other.thread_);
            return *this;
        }
    
        std::thread &operator*(){
            return thread_;
        }
    
        std::thread const &operator*() const{
            return thread_;
        }
    
        std::thread *operator->(){
            return & operator*();
        }
    
        std::thread const *operator->() const{
            return & operator*();
        }
    
        auto get_id() const{
            return thread_.get_id();
        }
    
        auto join(){
            if (thread_.joinable())
                thread_.join();
        }
    
        ~ScopedThread(){
            join();
        }
    
    private:
        std::thread thread_;
    };