Can compiler generate std::move for a last use of lvalue automatically?

☆樱花仙子☆ 提交于 2019-11-27 09:41:05

No. Consider:

using X = std::shared_ptr<int>;
void g(X);
void f() {
    X b = std::make_shared<int>();
    int &i = *b;
    g(b);              // last use of 'b'
    i = 5;
}

In general, the compiler cannot assume that altering the semantics of copies, moves and destructors of X will be a legitimate change without performing analysis on all the code surrounding the use of b (i.e., the whole of f, g, and all the types used therein).

Indeed, in some cases whole-program analysis may be necessary:

using X = std::shared_ptr<std::lock_guard<std::mutex>>;
std::mutex i_mutex;
int i;
void g(X);
void f() {
    X b = std::make_shared<std::lock_guard<std::mutex>>(i_mutex);
    g(b);              // last use of 'b'
    i = 5;
}

If b is moved, this introduces a data race against other threads that synchronize access to i using i_mutex.

Could a compiler do it? Only as an explicit language extension, because the standard doesn't allow them to make such an optimization without that.

Should they do it? No. The meaning of g(b) should be based on the definition of g and b. g should be some callable type, which has an overload that takes something that b can be implicitly converted into. Given access to the definition of all available gs, and the definition of b, you should be able to determine exactly what function will be called.

To allow this "optimization" now means that this is impossible. g(b) might perform a move, and it might not, depending on exactly where g(b) happens to be in a function. That's not a good thing.

return is allowed to get away with it, but only because it still has the same meaning. return b will always attempt to move from b if b is a value-type who's lifetime is restricted to the scope of the function.

(...) assuming a generic case the compiler does not know anything about how is move, copy or destruct implemented for the X class?

No, compilers are not allowed to do optimisations based on faith.

For clarity, this question is unrelated to copy elision: compilers may be allowed to elide a copy, but they cannot change copies to moves willy-nilly.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!