【问题标题】:What kind of optimizations does rvalue guarantee?右值保证什么样的优化?
【发布时间】:2015-08-20 14:13:27
【问题描述】:

我想用右值构造一个对象。

class BigDataClass{
public:
    BigDataClass(); //some default BigData
    BigDataClass(BigDataClass&& anotherBigData);
private:
    BigDataClass(BigDataClass& anotherBigData);

    BigDataPtr m_data;
};

所以现在我想做这样的事情:

BigDataClass someData;
BigDataClass anotherData(std::move(someData));

所以现在 anotherData 得到 rValue。事实上,它是一个过期值,所以 http://en.cppreference.com/w/cpp/utility/move 现在声明编译器 有机会通过移动优化 anotherData 的初始化 someData 到另一个。

在我看来,我们实际上可以得到 2 个不同的东西:

  1. 优化方法:数据移动。它经过优化,速度很快,我们很高兴
  2. 未优化的方法:未移动数据。我们必须将数据从对象复制到另一个对象并从第一个对象中删除数据(据我所知,一旦我们无法使用它,将对象更改为右值,因为它没有数据所有权,它持有)。事实上,由于删除操作,它甚至比使用左值引用的初始化还要慢。

我们真的可以得到如此未优化的数据初始化方式吗?

【问题讨论】:

  • 如果新对象应该获得所有权,那么通常没有什么可以为旧对象释放(它的指针应该被清空)——唯一的开销是执行解构函数
  • 我不明白“可以得到 2 种不同的东西”部分。你写课程,你决定。如果不优化移动,而是复制每个成员,那么你创建了一个合法但低效的“移动”构造函数。规则只说移动构造函数必须使源处于可破坏状态;因此,保持源不变是有效的。
  • 那是我弄错了

标签: c++ c++11 optimization rvalue


【解决方案1】:

你说:

所以现在 anotherData 得到 rValue。事实上,这是一个过期值,所以正如http://en.cppreference.com/w/cpp/utility/move 所说,compiler 现在有机会通过将 someData 移动到另一个来优化 anotherData 的初始化。

其实上面写的是:

代码接收这样一个 xvalue 有机会通过将数据移出参数来优化不必要的开销,使其处于有效但未指定的状态。

也就是说,这里负责优化的是代码,而不是编译器。 std::move(someData) 所做的所有事情都是将其参数转换为右值引用。鉴于BigDataClass 有一个接受右值引用的构造函数,该构造函数是首选的,并且该构造函数 是被调用的构造函数。从编译器的角度来看,这里没有任何改变的余地。因此,代码将执行 BigDataClass(BigDataClass&&) 构造函数所做的任何事情。

【讨论】:

  • 这是一个愚蠢的引用,因为 code 没有“做”任何事情。
  • 我现在很明白了。谢谢。
  • @LightnessRacesinOrbit 重新措辞(主要是通过删除以支持 Notes 中的扩展讨论)
  • “也就是说,这里是负责优化的代码”恐怕还是没有意义
【解决方案2】:

您似乎对什么是优化和什么不是优化感到困惑。使用移动构造函数(如果可用)不是优化,它是标准规定的。不是编译器有这个机会,它必须这样做。 另一方面,复制省略是编译器有机会执行的优化。它的可靠性取决于您的编译器(尽管他们非常一致地应用它)和实际的功能代码。

【讨论】:

    【解决方案3】:

    你想想优化器可以用移动语义做什么。本身就没有!您,编码员,必须实现代码,这是与具有 const ref 的构造函数相比的优化代码。

    问题可以反过来: 如果编译器已经知道你有一个右值,它作为 const ref 传递给构造函数,编译器就能够像在构造函数本身中生成值一样进行构造。复制省略经常由最新的编译器完成。这里的问题是(对我而言)我应该花费多少精力来编写一些右值引用结构来获得与编译器已经为我即时构建的结果相同的结果。

    好的,在 c++11 中,您有很多机会来处理通过算法转发和移动的代码。是的,可以产生一些好处。但我只看到模板代码的好处,因为我需要将一些参数移动/转发到(元)模板函数。

    反之亦然:处理右值引用必须小心谨慎,有效但未定义状态的含义会给使用您的接口实现的每个用户带来一些问题。另见:What can I do with a moved-from object?

    右值保证什么样的优化

    什么都没有。你必须实现它!

    【讨论】:

    • 解释得很好。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-29
    • 2020-04-13
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多