加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – std :: thread为什么对象被复制两次?

发布时间:2020-12-16 05:04:17 所属栏目:百科 来源:网络整理
导读:为什么在下面的示例代码中,对象被复制两次?根据线程类的文档构造函数将所有参数复制到线程本地存储,因此我们有理由进行第一次复制.第二个怎么样? class A {public: A() {cout "[C]" endl;} ~A() {cout "[~D]" endl;} A(A const src) {cout "[COPY]" endl;}
为什么在下面的示例代码中,对象被复制两次?根据线程类的文档构造函数将所有参数复制到线程本地存储,因此我们有理由进行第一次复制.第二个怎么样?
class A {
public:
    A() {cout << "[C]" << endl;}
    ~A() {cout << "[~D]" << endl;}
    A(A const& src) {cout << "[COPY]" << endl;}
    A& operator=(A const& src) {cout << "[=}" << endl; return *this;}

    void operator() () {cout << "#" << endl;}
};

void foo()
{
    A a;
    thread t{a};
    t.join();
}

上面的输出:

[C]
[COPY]
[COPY]
[~D]
#
[~D]
[~D]

编辑:
是的,添加移动构造函数后:

A(A && src) {cout << "[MOVE]" << endl;}

输出是这样的:

[C]
[COPY]
[MOVE]
[~D]
#
[~D]
[~D]

解决方法

对于您想要移动或避免复制的任何内容,首选移动构造函数和std :: move.

但为什么这不会自动发生在我身上?

移入C是保守的.它通常仅在您明确编写std :: move()时才会移动.这样做是因为移动语义,如果超出非常明确的情况,可能会破坏旧代码.出于这个原因,自动移动通常仅限于非常谨慎的环境.

为了避免在这种情况下复制,你需要使用std :: move(a)(即使将它传递给std :: thread)来转移.它第一次复制的原因是因为std :: thread无法保证在完成构造std :: thread之后该值将存在(并且您没有明确地将其移入).因此,它会做安全的事情并制作副本(不要使用引用/指针指向您传入的内容并存储它:代码不知道您是否将它保持活着).

同时使用移动构造函数和使用std :: move将允许编译器最大限度地有效地移动您的结构.如果您正在使用VC(使用CTP或不使用CTP),则必须显式编写移动构造函数,否则MSVC将(甚至有时会错误地)声明并使用Copy构造函数.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读