简体   繁体   English

std::move 与复制省略

[英]std::move versus copy elision

The following code compiles without warnings in Visual Studio 2019 msvc x64:以下代码在 Visual Studio 2019 msvc x64 中编译时没有警告:

class ThreadRunner {
public:
    void start() {
        m_thread = std::move(std::thread(&ThreadRunner::runInThread, this));
    }
    
private:
    void runInThread() {
        for (int i = 0; i < 1000 * 1000; i++) {
            std::cout << "i: " << i << "\n";
        }
    };
    std::thread m_thread;
};

However if I compile the same code with x64-Clang I get the following warning:但是,如果我使用 x64-Clang 编译相同的代码,则会收到以下警告:

warning : moving a temporary object prevents copy elision [-Wpessimizing-move]

Does this mean that I should have written:这是否意味着我应该写:

m_thread = std::thread(&ThreadRunner::runInThread, this);

instead?反而? And the compiler would have optimized away ("copy elided") the temporary variable?并且编译器会优化掉(“复制省略”)临时变量?

Will msvc x64 also copy elide the temporary variable? msvc x64 也会复制省略临时变量吗?

I did an experiment:我做了一个实验:

struct B {
    void f1() {
        a = A(5);
    }
    void f2() {
        A tmp = A(5);
        a = tmp;
    }
    void f3() {
        a = std::move(A(5));
    }
    void f4() {
        A tmp = A(5); 
        a = std::move(tmp);  
    }
    A a;
};

f1, f3 and f4 produce the same sequence of calls to A member functions: f1、f3 和 f4 产生对 A 成员函数的相同调用序列:

default ctor
ctor
move = operator

f2 produce another result: f2 产生另一个结果:

default ctor
ctor
= operator

The two versions两个版本

m_thread = std::thread(&ThreadRunner::runInThread, this);

and

m_thread = std::move(std::thread(&ThreadRunner::runInThread, this));

behave identically.行为相同。 No elision is possible in either case, since this is assignment to, not initialization of, m_thread .在任何一种情况下都不能省略,因为这是对m_thread的赋值,而不是初始化。 The temporary object must be constructed and then there will be a move assignment from it in either version.必须构造临时 object,然后在任一版本中都会有一个移动分配。

The hint is still correct though, since std::move on a temporary either doesn't have any effect at all (as here) or prevents elision if used in a context where copy elision would otherwise be allowed/mandatory, for example if this was the initializer of m_thread instead of an assignment to it.提示仍然是正确的,因为std::move临时或者根本没有任何效果(如这里),或者如果在允许/强制复制省略的上下文中使用,则防止省略,例如,如果这个是m_thread的初始化程序,而不是对它的赋值。

Does this mean that I should have written:这是否意味着我应该写:

 m_thread = std::thread(&ThreadRunner::runInThread, this);

instead?反而?

Yes, it means that and you should have.是的,这意味着你应该拥有。 std::thread(&ThreadRunner::runInThread, this) is a prvalue, and you gain nothing by casting it to an xvalue. std::thread(&ThreadRunner::runInThread, this)是纯右值,通过将其转换为 xvalue,您一无所获。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM