【问题标题】:c++ Creating a new thread from a member function and moving the object and the entirec ++从成员函数创建一个新线程并移动对象和整个
【发布时间】:2018-04-19 08:19:38
【问题描述】:

根据下面的代码,myClass1 对象和 myClass2 obj(这是 myClass1 对象的成员)是否会随着它们的内存移动到新线程(如 std::move())?

class myClass1{

  public:
   myClass2 obj;

    myClass1(myClass2 * obj) {
        this.obj = *obj;

    }
    thread spawn() {
        return std::thread([this] { this->Run(); });
    }
    void Run() {
        cout << "new thread" << endl;
    }
}
myClass2{
   public :
    string str;
  MyClass2(string str){
    this.str = str;
}

}
int main(){
  myClass1 object(new myClass2("test"));
  thread t = object.spawn();
 t.join();
 ........
}

【问题讨论】:

  • 这还能编译吗?
  • 请尝试创建Minimal, Complete, and Verifiable Example 并展示给我们。
  • 它只是为了展示概念,但如果你想编译它,它应该有一个新线程的连接和一个 myclass2 的定义:)
  • “它应该有...”你应该提供它
  • 您仍然没有可编译的示例。在您的构造函数中,this.obj = obj; 是一个类型错误。您想要myClass2 类型的 还是指向myClass2 的(n 拥有)原始指针?

标签: c++ multithreading c++11 memory


【解决方案1】:

就目前而言,您的main 将调用std::terminate,因为您丢弃了可连接的std::thread

如果你加入它,main 将阻塞直到线程完成。 object 将在 Run 的整个持续时间内保持活动状态。

如果你分离它,main 可能在线程之前结束,object 将不复存在,myClass1::Run 中的this 将无效。未定义的行为。

整理你的代码

class myClass1 {
    myClass2 obj;

public:
    // Take by rvalue, uses the move constructor for obj
    myClass1(myClass2 && obj) : obj(obj) {}

    std::thread spawn() {
        return std::thread([this] 
        {
            // This is suspicious, but safe
            auto self = std::move(*this); 
            self.Run(); 
        });
    }

    void Run() {
        std::cout << "new thread" << std::endl;
    }
}

int main(){
    // new is not required
    myClass1 object(myClass2("test"));
    object.spawn().join();
    /* other stuff, not involving object */
    return 0;
}

更多的整理

class myClass1 {
    myClass2 obj;

public:
    // Take by rvalue, uses the move constructor for obj
    myClass1(myClass2 && obj) : obj(obj) {}

    void Run() {
        std::cout << "new thread" << std::endl;
    }
}

int main() {
    // Just create the instance of myClass1 as a parameter to `std::thread`'s constructor
    std::thread(&myClass1::Run, myClass1(myClass2("test"))).join();
    /* other stuff */
    return 0;
}

【讨论】:

  • 亲爱的 Caleth 我知道你的观点,正如我在问题的评论中提到的那样,在 main 的末尾我添加了 .... 其中包含 join.my 的问题是关于将对象移动到它自己的成员函数也通过移动它的内存来实现
  • @AmirRasti 您没有移动任何对象。您创建this 指针的一个副本,它成为Run 内的this 指针
  • 你必须 std::move(*this) 进入 lambda 中的本地,然后在该本地调用 Run
  • 那么请将它作为一个不好的答案发布。
  • @AmirRasti 我有一个替代方案,可以避开std::move(*this)
【解决方案2】:

没有;创建线程不会神奇地使线程获得该内存的所有权。如果你在栈上创建一个对象,就创建一个使用它的线程;然后展开堆栈,销毁对象;在线程仍在运行的情况下,您将有未定义的行为。

如果您想将某些数据的所有权授予线程,最简单的方法是使用共享指针。

【讨论】:

  • 谢谢,在我的情况下,我想将我的 obj 及其所有字段的所有权交给新线程,以便在线程完成时释放所有内存。如果您修改此代码以实现这一点我会回答你的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多