复制和交换总是最好的解决方案? [英] Is copy-and-swap always the best solution?

查看:121
本文介绍了复制和交换总是最好的解决方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在中推荐了复制和交换的习语href =http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom>各种 地方作为为赋值运算符实现强异常安全的推荐/最佳/唯一方式。在我看来,这种方法也有一个缺点。

I have seen the copy-and-swap idiom recommended in various places as the recommended/best/only way to implement strong exception safety for the assignment operator. It seems to me that this approach also has a downside.

考虑下面的简化向量类,它使用复制和交换:

Consider the following simplified vector-like class which utilizes copy-and-swap:

class IntVec {
  size_t size;
  int* vec;
public:
  IntVec()
    : size(0),
      vec(0)
  {}
  IntVec(IntVec const& other)
    : size(other.size),
      vec(size? new int[size] : 0)
  {
    std::copy(other.vec, other.vec + size, vec);
  }

  void swap(IntVec& other) {
    using std::swap;
    swap(size, other.size);
    swap(vec, other.vec);
  }

  IntVec& operator=(IntVec that) {
    swap(that);
    return *this;
  }

  //~IntVec() and other functions ...
}

通过拷贝构造函数实现赋值可能是高效的,并且保证了异常安全性,但也可能导致不必要的分配,甚至可能导致内存不足的错误。

Implementing the assignment via the copy constructor may be efficient and guarantee exception safety, but it can also cause an unneeded allocation, potentially even causing an uncalled for out-of-memory error.

考虑将700MB IntVec 分配给1GB IntVec 具有<2GB堆限制的计算机。最佳赋值将意识到它已经分配了足够的内存,并且仅将数据复制到其已经分配的缓冲器中。复制和交换实现将导致在释放1GB的缓冲区之前分配另一个700MB的缓冲区,导致所有3个缓冲区尝试同时存在于内存中,这将不必要地引起内存不足的错误。

Consider the case of assigning a 700MB IntVec to a 1GB IntVec on a machine with a <2GB heap limit. An optimal assignment will realize it already has enough memory allocated and only copy the data into it's already allocated buffer. The copy-and-swap implementation will cause an allocation of another 700MB buffer before the 1GB one is released, causing all 3 to try co-exist in memory at once, which will throw an out-of-memory error needlessly.

此实现将解决问题:

IntVec& operator=(IntVec const& that) {
  if(that.size <= size) {
    size = that.size;
    std::copy(that.vec, that.vec + that.size, vec);
  } else
    swap(IntVec(that));
  return *this;
}

所以底线是:

这是一个问题与复制和交换惯用法,或做正常的编译器优化以某种方式消除额外的分配,或者我忽略了一些问题,我的更好的版本的副本和交换解决,或者我

So the bottom line is:
Am I right that this is a problem with the copy-and-swap idiom, or do normal compiler optimizations somehow eliminate the extra allocation, or am I overlooking some problem with my "better" version that the copy-and-swap one solves, or am I doing my math/algorithms wrong and the problem doesn't really exist?

推荐答案

执行我的数学/算法错误,并且该问题不真的存在吗?

There are two problems with the implementation reusing the space


  • 如果您分配 very_huge_vect = very_small_vect; 将不会被释放。这可能是你想要的,也可能不是。

  • If you're assigning very_huge_vect = very_small_vect; the extra memory will not be released. This may be what you want or may be not.

在整数的情况下,一切都很好,但对于复制操作可能抛出异常?你会得到一个乱七八糟的数组,其中一部分的副本已经完成,并已被截断。

In case of integers all is fine, but what about objects for which the copy operation may throw an exception? You'll end up with a messed up array where part of the copy has been done and that has been truncated. Much better would be to leave the target untouched if the copy operation fails (what the swap idiom does).

由于复制操作失败,方式,作为一般规则,在极少数情况下,你可以找到看起来像总是最好的解决方案的任何东西。如果你正在寻找一个银弹,编程不会是正确的地方。

By the way, as a general rule, in very few cases you can find anything that looks like "always the best solution". If you're looking for a silver bullet, programming is not going to be the right place.

这篇关于复制和交换总是最好的解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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