【问题标题】:Automatic xvalue optimization自动 xvalue 优化
【发布时间】:2014-11-18 17:27:21
【问题描述】:

有点令人惊讶(对我来说),以下两个程序编译成不同的输出,后一个具有更好的性能(用 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;
    }
}

对比

#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编译

【问题讨论】:

  • 你传递给编译器的参数是什么?
  • 我的第一个猜测是,这会以意想不到的方式改变程序的语义,将复制变成移动。
  • @pmr:这也是我的怀疑,但我真的很想了解原因。天真地,它看起来确实像 xvalue 对我来说应该是什么。
  • 确实它可能是一种优化,但它肯定会影响程序本身的语义,即更改所有权。 IIRC 在第一个标准草案期间对此主题进行了很多讨论
  • 编译器只是安全的,在这种情况下它确实可以工作,但似乎编译器在 std 进行优化时没有使用“b 将不再被使用”的信息: :move 明确地告诉他

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


【解决方案1】:

Compilers can't break the as-if rule

如 §1.9/1 所述:

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

即编译器不能改变程序的可观察行为。自动(即使没有任何影响)将赋值转换为移动赋值会破坏此语句。

复制省略可以稍微改变这种行为,但这是由 §12.8/31 规定的。

如果你想使用 move 版本,你必须像后一个例子一样明确要求它。

【讨论】:

  • 好的,所以特别是程序员应该有可靠的复制/移动操作符/ctor调用。我不知何故认为要求程序员使这些操作在语义上兼容是明智的。我想这两种方法各有利弊,但我可以理解为什么标准对它的看法不同。
  • 在这个特定的代码中,它不会破坏 as-if 规则,因为没有输出
【解决方案2】:

让我们看下一个示例(请忽略来自operator=void 返回类型):

#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= 根据其参数有不同的行为。只有当编译器能够保持相同的可观察行为时,才允许编译器优化代码。

考虑到 bfunxvalue,虽然在调用时它不是 xvalue,但它会改变程序的可观察行为,这是标准不希望也不允许的.

【讨论】:

  • 谢谢,我知道构造函数调用的变化。我假设程序员需要以某种方式使移动构造函数/运算符和复制构造函数/运算符“语义匹配”,我想这就是我的缺陷!
猜你喜欢
  • 2018-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 2021-02-21
  • 2016-09-09
  • 2019-06-01
  • 1970-01-01
相关资源
最近更新 更多