“检查自分配"有什么问题?这是什么意思? [英] What is wrong with "checking for self-assignment" and what does it mean?

查看:16
本文介绍了“检查自分配"有什么问题?这是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Herb Sutter 的书 Exceptional C++ (1999) 中,他在第 10 项的解决方案中有文字:

In Herb Sutter's book Exceptional C++ (1999), he has words in item 10's solution:

异常不安全"和糟糕的设计"齐头并进.如果一段代码不是异常安全的,那通常没问题,可以简单地修复.但是,如果一段代码由于其底层设计而不能成为异常安全的,那几乎总是一个糟糕设计的信号.

"Exception-unsafe" and "poor design" go hand in hand. If a piece of code isn't exception-safe, that's generally okay and can simply be fixed. But if a piece of code cannot be made exception-safe because of its underlying design, that almost always is a signal of its poor design.

示例 1:具有两种不同职责的函数很难使异常安全.

Example 1: A function with two different responsibilities is difficult to make exception-safe.

示例 2:以必须检查自赋值的方式编写的复制赋值运算符可能也不是强异常安全

Example 2: A copy assignment operator that is written in such a way that it must check for self-assignment is probably not strongly exception-safe either

他所说的检查自我分配"是什么意思?

What does he mean by the term "check for self-assignment"?

【咨询】

Dave 和 AndreyT 向我们展示了检查自我分配"的确切含义.那挺好的.但问题还没有结束.为什么检查自我分配"会损害异常安全"(根据赫布萨特的说法)?如果调用者尝试进行自赋值,则该检查"的工作方式就好像从未发生过赋值一样.真的疼吗?

Dave and AndreyT shows us exactly what "check for self-assignment" means. That's good. But the question is not over. Why does "check for self-assignment" hurts "exception safety"(according to Hurb Sutter)? If the caller tries to do self-assignment, that "check" works as if no assignment ever occurs. Does it really hurt?

[备忘录 1] 在 Herb 书中后面的第 38 项对象标识中,他解释了自赋值.

[MEMO 1] In item 38 Object Identity later in Herb's book, he explains about self-assignment.

推荐答案

在这种情况下,更重要的问题是以必须检查自赋值的方式编写"是什么意思.

The more important question in this case is what "written in such a way that it must check for self-assignment" means.

这意味着设计良好的赋值运算符不应该需要检查自赋值.将对象分配给自身应该可以正常工作(即具有什么都不做"的最终效果),而无需对自分配执行显式检查.

It means that a well designed assignment operator should not need to check for self-assignment. Assigning an object to itself should work correctly (i.e. have the end-effect of "doing nothing") without performing as explicit check for self-assignment.

例如,如果我想实现一个简单的数组类

For example, if I wanted to implemented a simplistic array class along the lines of

class array {
  ...
  int *data;
  size_t n;
};

并提出了以下赋值运算符的实现

and came up with the following implementation of the assignment operator

array &array::operator =(const array &rhs) 
{
  delete[] data;

  n = rhs.n;
  data = new int[n];
  std::copy_n(rhs.data, n, data);

  return *this;
}

该实现将被认为是糟糕的",因为它在自我分配的情况下显然会失败.

that implementation would be considered "bad" since it obviously fails in case of self-assignment.

为了修复"它,可以添加一个明确的自赋值检查

In order to "fix" it one can either add an explicit self-assignment check

array &array::operator =(const array &rhs) 
{
  if (&rhs != this) 
  {
    delete[] data;

    n = rhs.n;
    data = new int[n];
    std::copy_n(rhs.data, n, data);
  }

  return *this;
}

或遵循无需检查"的方法

or follow a "check-less" approach

array &array::operator =(const array &rhs) 
{
  size_t new_n = rhs.n;
  int *new_data = new int[new_n];
  std::copy_n(rhs.data, new_n, new_data);

  delete[] data;

  n = new_n;
  data = new_data;

  return *this;
}

后一种方法更好,因为它可以在自赋值情况下正常工作,而无需显式检查它.(从异常安全的角度来看,这个实现还很不完美,这里是为了说明处理自赋值的检查"和无检查"方法之间的区别).后面的 check-less 实现可以通过众所周知的 copy-and-swap 惯用语来写得更优雅.

The latter approach is better in a sense that it works correctly in self-assignment situations without making an explicit check for it. (This implementation is still far for perfect from the exception safety point of view, it is here to illustrate the difference between "checked" and "check-less" approaches to handling self-assignment). The later check-less implementation can be written more elegantly through the well-known copy-and-swap idiom.

这并不意味着您应该避免对自分配进行显式检查.从性能的角度来看,这种检查确实有意义:执行一长串操作只是为了最终无所作为"是没有意义的.但是在设计良好的赋值运算符中,从正确性的角度来看,这种检查应该是不必要的.

This does not mean that you should avoid explicit checks for self-assignment. Such check do make sense from the performance point of view: there's no point in carrying out a long sequence of operations just to end up "doing nothing" in the end. But in a well-designed assignment operator such checks should not be necessary from the correctness point of view.

这篇关于“检查自分配"有什么问题?这是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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