C ++ Rvalue引用和移动语义

C ++ 03存在可能隐式发生的不必要副本的问题。 为此,C ++ 11引入了rvalue referencesmove semantics 。 现在我的问题是,这个不必要的复制问题是否也存在于C#和java等语言中,还是只是一个C ++问题? 换句话说,与C#或Java相比, rvalue references使C ++ 11更高效?

就C#而言(允许运算符重载),假设我们有一个数学向量类,我们就像这样使用它。

 vector_a = vector_b + vector_c; 

编译器肯定vector_b + vector_c转换为某个临时对象(让我们称之为vector_tmp )。

现在我不认为C#可以区分临时右值(例如vector_tmp或左值(例如vector_b ,因此我们必须将数据复制到vector_a ,这可以通过使用rvalue references和在C中move semantics来轻松避免。 ++ 11。

C#和Java中的类引用在C ++中具有shared_ptr的一些属性。 但是,rvalue引用和移动语义更多地与临时值类型相关,但C#中的值类型与C ++值类型相比非常不灵活,而且根据我自己的C#经验,你最终会得到类,而不是结构,大多数的时间。

所以我的假设是,Java和C#都不会从那些新的C ++特性中获得太多利益,这使得代码可以安全地假设某些东西是否是临时的,而不是复制让它只是窃取内容。

是的,在C#和java中有不必要的复制操作。

与C#或Java相比,右值引用能否使C ++ 11更高效?

答案是肯定的。 🙂

因为Java和C#中的类使用引用语义,所以这些语言中永远不会有任何对象的隐式副本。 问题移动语义解决在Java和C#中从未存在过。

我认为它可能发生在Java中。 请参阅下面的add和add_to操作。 add创建一个结果对象来保存矩阵添加操作的结果,而add_to只是将rhs添加到此。

 class Matrix { public static final int w = 2; public static final int h = 2; public float [] data; Matrix(float v) { data = new float[w*h]; for(int i=0; i 

因此,我认为这取决于您为类提供给用户的function。

问题出现了很多。 有人想要抓住一个别人无法修改的对象的唯一副本。 我怎么做?

  1. 对某人给我的任何对象进行深层复制? 这样可行,但效率不高。
  2. 让人们给我一个新的对象而不是保留副本? 如果你勇敢的话,这会更快。 错误可能来自一段完全不相关的代码,几小时后修改对象。
  3. C ++样式:将输入中的所有项目移动到我自己的新对象。 如果调用者意外再次尝试使用该对象,他将立即看到问题。
  4. 有时,C#只读集合可以提供帮助。 但在我的经历中,这通常是一种痛苦。

这就是我在说的:

 class LongLivedObject { private Dictionary  _settings; public LongLivedObject(Dictionary  settings) { // In C# this always duplicates the data structure and takes O(n) time. // C++ will automatically try to decide if it could do a swap instead. // C++ always lets you explicitly say you want to do the swap. _settings = new Dictionary (settings); } } 

这个问题是Clojure和其他function语言的核心!

总之,是的,我经常希望我在C#中使用C ++ 11样式的数据结构和操作。

您可以尝试模拟移动语义。 例如,在Trade-Ideas Philip的例子中,您可以传递自定义MovableDictionary而不是Dictionary

 public class MovableDictionary // : IDictionary, IReadOnlyDictionary... { private Dictionary _map; // Implement all Dictionary's methods by calling Map's ones. public Dictionary Move() { var result = Map; _map = null; return result; } private Dictionary Map { get { if (_map == null) _map = new Dictionary(); return _map; } } }