If you’re not keeping the parameter, then you still want to have separate T const& and T&& ...

栏目: IT技术 · 发布时间: 6年前

内容简介:If you’re not keeping the parameter, then you still want to have separateFebruary 20th, 2020Last time, I noted that

If you’re not keeping the parameter, then you still want to have separate T const& and T&& overloads

If you’re not keeping the parameter, then you still want to have separate T const& and T&& ...

Raymond

February 20th, 2020

Last time, I noted that if you plan on keeping the parameter anyway, then there’s no need to have separate T const& and T&& overloads . However, the converse also applies: If you’re not keeping the parameter, then you still want to have separate T const& and T&& overloads.

To recap, we started with a class like this:

class Widget
{
public:
  void SetValues(std::vector<int> const& values)
  {
    m_values = values;
  }

  void SetValues(std::vector<int>&& values)
  {
    m_values = std::move(values);
  }
private:
  std::vector<int> m_values;
};

We were able to simplify this to

class Widget
{
public:
  void SetValues(std::vector<int> values)
  {
    m_values = std::move(values);
  }

private:
  std::vector<int> m_values;
};

because we are going to keep the parameter either way. (The old way resulted in either a copy or a move. The new way produces either a copy+move or a move. The expectation is that a single move is relatively inexpensive.)

However, the simplification doesn’t apply if we are not the ones consuming the value.

Widget CreateWidgetWithValues(std::vector<int> values)
{
  Widget widget;
  widget.SetValues(std::move(values));
  return widget;
}

In this case, we are moving the values onward to the SetValues method, who is the final consumer. Writing the method this way generates an extra move constructor, because we have to move the value from our inbound parameter into the outbound parameter to SetValues . We also incur an extra destruction of our now-empty inbound parameter. If the parameter is passed through multiple layers, each layer adds an extra move constructor and destruction.

Since we are not the final consumer, we should forward the parameter.

template<typename Values>
Widget CreateWidgetWithValues(Values&& values)
{
  Widget widget;
  widget.SetValues(std::forward<Values>(values));
  return widget;
}

Unfortunately, this causes us to break existing code, since you cannot forward uniform initialization.

// doesn't work any more
CreateWidgetWithValues({ range.begin(), range.end() });

We end up returning to the overload.

Widget CreateWidgetWithValues(const std::vector<int>& values)
{
  Widget widget;
  widget.SetValues(values);
  return widget;
}

Widget CreateWidgetWithValues(std::vector<int>&& values)
{
  Widget widget;
  widget.SetValues(std::move(values));
  return widget;
}

I’m not too happy with this, though. Maybe there’s an easier way. Let me know.

Bonus chatter : The Microsoft compiler makes the function responsible for destructing its inbound parameters, in which case the code to destruct the std::vector<int> is part of the consuming function and is therefore shared. gcc and clang make it the caller’s responsibility, so the destruction of the parameter is repeated at each call site.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数学建模(原书第5版)

数学建模(原书第5版)

[美] Frank R. Giordano、[美] William P.Fox、[美] Steven B.Horton / 叶其孝、姜启源 / 机械工业出版社 / 2014-10-1 / 99.00元

《华章数学译丛:数学建模(原书第5版)》旨在指导学生初步掌握数学建模的思想和方法,共分两大部分:离散建模和连续建模,通过本书的学习,学生将有机会在创造性模型和经验模型的构建、模型分析以及模型研究方面进行实践,增强解决问题的能力。 《华章数学译丛:数学建模(原书第5版)》对于用到的数学知识力求深入浅出,涉及的应用领域相当广泛,适合作为高等院校相关专业的数学建模教材和参考书,也可作为参加国内外数......一起来看看 《数学建模(原书第5版)》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具