当前位置: 首页 > 知识库问答 >
问题:

为什么参数在构造std::线程时移动了两次

颜永怡
2023-03-14

考虑这个程序本质上创建了<代码> STD::线程< /代码>,调用函数<代码>函数()/代码>以<代码> ARG作为参数:

#include <thread>
#include <iostream>

struct foo {
   foo() = default;
   foo(const foo&) { std::cout << "copy ctor" << std::endl; }
   foo(foo&&) noexcept { std::cout << "move ctor" << std::endl; }
};

void func(foo){}

int main() {
   foo arg;
   std::thread th(func, arg);
   th.join();
}

我的输出是

copy ctor
move ctor
move ctor

据我所知,arg在线程对象中内部复制,然后作为右值(移动)传递给func()。所以,我期待一个副本建设和一个移动建设。

为什么会有第二步建设?

共有2个答案

仰城
2023-03-14

所以,我期望一次复制构造和一次移动构造。

标准实际上并没有这么说。允许实现执行额外的内部移动构造。

但这样做可能会降低效率。这是https://gcc.gnu.org/PR69724并且已经在即将发布的GCC10版本中修复。

石超
2023-03-14

通过值将参数传递给func,该值应构成第二步。显然,std::thread在调用func之前会在内部存储它一次,就标准而言,AFAIK是绝对合法的。

 类似资料:
  • 请考虑以下程序: 如果我运行该程序,我会得到(GoBolt): ...这符合我的预期。但是,如果在线上我将析构函数标记为可能抛出,那么我得到: ...即使用复制因子代替移动因子。为什么会这样呢?复制似乎不能防止移动所必须的破坏。 相关问题: < li >是否要求std::vector使用移动而不是复制? < li >当向量增长时,如何实施移动语义? < li >向量重新分配使用复制而不是移动构造函

  • 问题内容: 我写了一个实现Runnable的类,以同时运行到另一个线程。主线程处理侦听串行端口,而第二个线程将处理向该端口发送数据。 第一个线程从第二个开始,如下所示: 这可行,但是我的编译器会标出警告语:在构造函数中启动新线程很危险。为什么是这样? 这个问题的第二部分是:如何在一个线程(串行端口侦听线程)中运行循环,并在第二个线程中键入退出命令。如何获得第一个终止的线程?谢谢。 问题答案: 你的

  • 当Java中给出参数构造函数时,为什么默认的无参数构造函数会失败? 这个设计有什么意义? 例如:

  • 问题内容: 必须使用无参数构造函数(像Hibernate这样的工具会在此构造函数上使用反射来实例化对象)。 我得到了这个手挥手的答案,但是有人可以进一步解释吗?谢谢 问题答案: hibernate,并且通常通过反射创建对象的代码用于创建类的新实例。此方法需要一个公共的无参数构造函数才能实例化该对象。对于大多数用例,提供无参数构造函数不是问题。 有一些基于序列化的技巧可以解决没有no-arg构造函数

  • 在C#、C和Java中,当你创建一个带参数的构造函数时,默认的无参数构造函数就消失了。我一直只是接受这个事实,但现在我开始想为什么。 这种行为的原因是什么?这仅仅是一个“安全度量/猜测”,说“如果你已经创建了自己的构造函数,你可能不希望这个隐含的函数四处游荡”?或者它有一个技术原因,使得编译器不可能在你自己创建构造函数后添加一个?

  • 我正试图用BlueJ完成一项为uni完成的任务,但我在第一个障碍上遇到了障碍。 在赋值中,我们得到了一个类,以及该类的构造函数、方法和参数的名称。我们不允许更改这些,因为赋值部分地由测试单元标记(或类似的东西)。 该类的一个构造函数如下所示 我已经(部分)完成了 我不明白的是为什么-为什么他们使用作为构造函数的参数?这样做有什么好处? (我想这样做肯定有好处(如果没有,功能就不会存在),但我不明白