【问题标题】:defining operator + , = and +=定义运算符 + 、 = 和 +=
【发布时间】:2011-03-20 18:10:41
【问题描述】:

我曾经从一个 C++ 笔记中读到以下语句,

在 C++ 中,定义运算符 + 和 = 并没有赋予 += 正确的含义。此语言设计错误已在 C# 中修复

我想知道这句话到底想说什么?这和运算符重载有关吗?

【问题讨论】:

  • 作者不是 C++ 专家。忽略他或她。
  • 我认为该声明的作者想说他对C++一无所知。特别是他不明白为什么在 C++ 中手动重载 += 是有意义的,为什么在 C# 中没有意义。您在哪里找到了该声明?

标签: c# c++ operator-overloading


【解决方案1】:

我更喜欢 C++ 运算符重载机制。在我看来,这绝对不是设计错误。

+=+= 是三个不同的运算符。如果你想使用+=,你需要重载+=。重载 += 不会使 += 工作。

我想补充一点,就 C++ 而言,E1 += E2 E1 只被评估一次。我不知道 C# 中的确切规则。

【讨论】:

  • 在 C# 中,不会对任何内容进行两次评估。但是E1 的getter 和setter 都会被求值。
  • @Ben :这就是为什么我说我不知道​​ C# 中的规则。谢谢你的信息顺便说一句:-)
【解决方案2】:

它说,在 C# 中,如果您重载了 operator + C# 将自动将 operator += 模拟为 + 和 = 的组合(a=a+b 等于 a+=b)。在 C++ 中它没有被实现,但它不是一个错误。在 C++ 中,+ 和 = 不会给你 +=,因为大多数情况下 += 比 + 工作得更快,因为不需要再创建一个对象。

这就是为什么大多数运算符 + 是使用 += 运算符编写的。考虑闲置代码:

class foo
{
public:
   foo& operator+=(const foo& rhs)
   {
   //.......
   }
};
const foo operator+(const foo& lhs,const foo& rhs)
{
   foo temp = lhs;
   return temp+= rhs;
}

【讨论】:

  • 第一句没有意义,因为C#不允许重载运算符=
  • 并且允许在不能重载 = 的语言中重载 += 是没有意义的。由于具有重载+= 的对象在没有重载= 的情况下改变左侧的对象具有严重破坏的语义。
  • C# 不允许运算符重载 = 因为它不允许直接指针管理。它的行为是根据它是引用类型还是值类型来固定的
  • @Ashot: +1,但建议按值传递而不是按引用传递,然后在函数内部进行复制,按值传递参数给编译器不同优化机会。
  • @Ben Voigt 你是对的,在我的第一个答案版本中,我已经通过了价值,但比我想象的,这样的代码看起来对初学者来说有点混乱。
【解决方案3】:

这意味着在 C++ 中,如果你为你的类定义了自己的运算符 + 和运算符 =,这并不意味着你的类会自动支持 += 运算符。如果您希望 += 运算符适用于您的班级,则必须明确且单独定义 +=

在 C# 中,如果我理解正确的话,为你的类定义运算符 += 也意味着你将能够在你的类中使用运算符 +=+= 将通过运算符+ 和运算符= 的组合来“模拟”。例如。表达式a += b 将被解释为a = a + b

它在 C++ 中不是这样工作的。如果您没有明确定义+=a += b 将导致编译器错误,即使您定义了+=

【讨论】:

  • 我想补充一点,+= 的创建不会自动创建+= 运算符,这不是一个错误。 + 从两个对象创建一个新对象并返回新对象。 +=无需创建新对象,直接修改target-object即可。
  • C# 甚至不允许重载运算符=
【解决方案4】:

C# 不允许运算符重载 =,因为它不允许直接指针管理。它的行为是基于它是引用类型还是值类型而固定的。出于同样的原因,您不能重载 += 。它的含义将始终是求和和赋值。因此,您只能决定 + 对您的数据结构的含义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2018-09-14
    • 2013-04-14
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多