【问题标题】:C++ operator overloading for pointers指针的 C++ 运算符重载
【发布时间】:2013-04-11 08:14:28
【问题描述】:

我想知道(只是出于好奇)为什么 C++ 中不允许将运算符重载用于指针。我的意思是这样的:

Vector2d* operator+(Vector2d* a, Vector2d* b) { return new Vector2d(a.x + b.x, a.y + b.y); }

Vector2d* a = new Vector2d(1, 1); 
Vector2d* b = new Vector2d(2, 2); 
Vector2d* c = a + b; 

注意 'a + b' 如何创建一个新的 Vector 对象,然后只将其地址复制到 'c' 中,而不调用复制构造函数。所以它可以解决新的右值引用解决的相同问题。此外,据我所知,它几乎等同于在 C# 中使用运算符重载时发生的情况(但我在这里可能错了,我从未真正使用过 C#),以及为什么在 C# 中不需要右值引用。

确实,右值引用解决方案更好,因为它允许基于堆栈的对象,而这种重载将强制所有 Vector2d 对象都存在于堆上,但它似乎仍然很容易实现在编译器中,可能在右值引用出现之前几年。使用自定义分配器,它甚至不会那么慢。

那么这仅仅是因为“最小惊喜”原则是非法的,还是还有其他原因?

【问题讨论】:

  • 您也可以拥有指向基于堆栈的对象的指针。
  • ab 中使用new 有什么意义? (c 有点道理,但还是在自找麻烦)
  • 我认为这是最不意外的原则。例如 operator- 在两个指针上定义。因此,在您的示例中,您将定义 operator+ 和 operator- ,但做的事情完全不同。
  • new Vector2d -- 它是什么,Java?

标签: c++ operator-overloading rvalue-reference


【解决方案1】:

确实,右值引用解决方案更好,因为它允许基于堆栈的对象,而这种重载将强制所有 Vector2d 对象都存在于堆上,但它似乎仍然很容易实现在编译器中,可能在右值引用出现之前几年。使用自定义分配器,它甚至不会那么慢。

那么这仅仅是因为“最小意外”原则而违法,还是还有其他原因?

  • 它没有正确链接...a + b + c 应该做什么,泄漏内存?
  • 指针算术在 C++ 中已经有了意义……这对于在类型之间保持一致很有用,否则例如算法无法在您的对象容器上正常工作。
  • 按值返回某些内容意味着调用者不需要清理对象:如果它使用空闲存储(堆)来存储实际数据,它将在必要时自动删除它。使始终如一的强大内存使用变得更容易。

注意 'a + b' 如何创建一个新的 Vector 对象,然后只将其地址复制到 'c' 中,而不调用复制构造函数。所以它可以解决新的右值引用解决的相同问题。

常用的返回值优化也解决了这个问题,帮助编译器安排将返回值直接构造到调用者的缓冲区中。

【讨论】:

  • 啊,指针算法,当然。我觉得有点愚蠢,因为我自己没有想到它。 :)
【解决方案2】:

主要原因是因为指针已经有了一定的 为它们定义的运算符的数量。如果我有两个变量 ab 类型为 MyType,我写 a - b,然后 读者知道他必须寻找超载或隐含的 转换。如果变量的类型为MyType*,则阅读器 可能会假设 a - b 是指针算术;有 这意味着其他事情会令人困惑,并且可能会 导致出现MyType 数组的问题(包括在 std::vector 的内部结构。

类似的考虑适用于许多其他运算符。 C++ 的指导方针是你应该能够扩展 语言,但不要改变它。 (而且我知道一元 & 是 此规则的例外。)

关于 C#,语言是不同的。在 C# 中, 指针不是对象;没有区别 MyTypeMyType*,并且指针上没有运算符。 而且 C# 不使用值语义(通常),其中大多数 C++ 中的对象将具有值语义,并且实际上 永远不会被动态分配。 (如果Vector2d 是什么意思 似乎意味着,它永远不应该在 C++ 中动态分配。)

【讨论】:

    猜你喜欢
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 2020-10-14
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    相关资源
    最近更新 更多