我应该总是移动`sink`构造函数或setter参数? [英] Should I always move on `sink` constructor or setter arguments?

查看:166
本文介绍了我应该总是移动`sink`构造函数或setter参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  struct TestConstRef {
std :: string str;
Test(const std :: string& mStr):str {mStr} {}
};

struct TestMove {
std :: string str;
Test(std :: string mStr):str {std :: move(mStr)} {}
};

在观看GoingNative 2013之后,我明白, sink 参数应该总是传递并通过 std :: move 移动。是 TestMove :: ctor 正确的方式应用此成语吗?是否有任何情况下 TestConstRef :: ctor 更好/更高效?





$ b b

琐碎的setter呢?我应该使用以下惯用法还是传递 const std :: string&

  struct TestSetter {
std :: string str;
void setStr(std :: string mStr){str = std :: move(str); }
};


解决方案

简单的答案是:






原因很简单,如果你按值存储,你可能需要移动(从一个临时)或复制(从I值)。







  • 如果你使用const-ref的参数,则临时绑定到const-ref,并且不能再次移动,因此你最终创建了一个(无用的)副本。 >
  • 如果以值为参数传递参数,则该值将从临时(移动)初始化,然后您自己从参数移动,因此不会进行复制。



一个限制:没有高效移动构造函数的类(例如 std :: array< T,N> ),因为这样做了两个副本而不是一个。



从l值(或const临时, ..)




  • 如果你接受const-ref的参数,那么什么都不会发生,然后你复制它

  • 如果以值的形式接受参数,则将其复制到参数中,然后从参数中移走,从而生成单个副本。



一个限制:类似于移动类似于复制的类。



所以,简单的答案是,在大多数情况下,通过使用一个sink你避免不必要的副本(替换它们的移动)。



移动构造函数与复制构造函数一样昂贵(或接近昂贵)在这种情况下,具有两个移动而不是一个副本是最差的。幸运的是,这样的类是罕见的(数组是一种情况)。


struct TestConstRef {
    std::string str;
    Test(const std::string& mStr) : str{mStr} { }
};

struct TestMove {
    std::string str;
    Test(std::string mStr) : str{std::move(mStr)} { }
};

After watching GoingNative 2013, I understood that sink arguments should always be passed by value and moved with std::move. Is TestMove::ctor the correct way of applying this idiom? Is there any case where TestConstRef::ctor is better/more efficient?


What about trivial setters? Should I use the following idiom or pass a const std::string&?

struct TestSetter {
    std::string str;
    void setStr(std::string mStr) { str = std::move(str); }
};

解决方案

The simple answer is: yes.


The reason is quite simple as well, if you store by value you might either need to move (from a temporary) or make a copy (from a l-value). Let us examine what happens in both situations, with both ways.

From a temporary

  • if you take the argument by const-ref, the temporary is bound to the const-ref and cannot be moved from again, thus you end up making a (useless) copy.
  • if you take the argument by value, the value is initialized from the temporary (moving), and then you yourself move from the argument, thus no copy is made.

One limitation: a class without an efficient move-constructor (such as std::array<T, N>) because then you did two copies instead of one.

From a l-value (or const temporary, but who would do that...)

  • if you take the argument by const-ref, nothing happens there, and then you copy it (cannot move from it), thus a single copy is made.
  • if you take the argument by value, you copy it in the argument and then move from it, thus a single copy is made.

One limitation: the same... classes for which moving is akin to copying.

So, the simple answer is that in most cases, by using a sink you avoid unnecessary copies (replacing them by moves).

The single limitation is classes for which the move constructor is as expensive (or near as expensive) as the copy constructor; in which case having two moves instead of one copy is "worst". Thankfully, such classes are rare (arrays are one case).

这篇关于我应该总是移动`sink`构造函数或setter参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆