自动xvalue优化

时间:2014-09-24 09:22:20

标签: c++ c++11 move-semantics xvalue

有点令人惊讶(对我来说),以下两个程序编译成不同的输出,后者有更好的性能(用gcc和clang测试):

#include <vector>
int main()
{
    std::vector<int> a(2<<20);
    for(std::size_t i = 0; i != 1000; ++i) {
        std::vector<int> b(2<<20);
        a = b;
    }
}

VS

#include <vector>
int main()
{
    std::vector<int> a(2<<20);
    for(std::size_t i = 0; i != 1000; ++i) {
        std::vector<int> b(2<<20);
        a = std::move(b);
    }
}

有人可以向我解释为什么编译器会(或可以)不自动在最后一个赋值中考虑b xvalue并在没有显式std::move强制转换的情况下应用移动语义吗?

修改:使用(g++|clang++) -std=c++11 -O3 -o test test.cpp

进行编译

2 个答案:

答案 0 :(得分:7)

Compilers can't break the as-if rule

如§1.9/ 1所述:

  

本国际标准中的语义描述定义了一个   参数化非确定性抽象机。这个国际   标准对符合结构没有要求   实现。特别是,他们不需要复制或模仿   抽象机器的结构。相反,符合实施   需要模仿(仅)抽象的可观察行为   机器如下所述

即。编译器无法更改程序的可观察行为。自动(即使没有任何反响)将分配转换为移动分配会破坏此陈述。

复制符号可以稍微改变这种行为,但这受§12.8/ 31的规定。

如果你想使用移动版本,你必须在后一个例子中明确要求它。

答案 1 :(得分:5)

让我们看一下下一个示例(请忽略来自void的{​​{1}}返回类型):

operator=

#include <iostream> struct helper { void operator=(helper&&){std::cout<<"move"<<std::endl;} void operator=(const helper&){std::cout<<"copy"<<std::endl;} }; void fun() { helper a; { helper b; a = b; } } void gun() { helper a; { helper b; a = std::move(b); } } int main() { fun(); gun(); } 具有不同的行为,具体取决于其参数。只有在能够保持可观察行为相同的情况下,才允许编译器优化代码。

考虑来自operator=b的{​​{1}},虽然它在调用时不是fun,但它会改变程序的可观察行为标准不希望也不允许。