【问题标题】:Why is overloading operator&() prohibited for classes stored in STL containers?为什么存储在 STL 容器中的类禁止重载 operator&()?
【发布时间】:2011-02-12 18:32:31
【问题描述】:

突然在this article ("problem 2") 中看到一条声明,如果该类具有重载的operator&(),则 C++ 标准禁止使用 STL 容器来存储类的元素。

重载了operator&()can indeed be problematic,但看起来默认的“address-of”运算符可以通过a set of dirty-looking casts that are used in boost::addressof() 轻松使用,并且被认为是可移植的和标准编译的。

为什么在存在boost::addressof() 解决方法的情况下,禁止对存储在 STL 容器中的类使用重载的 operator&()

【问题讨论】:

  • 出于好奇(没有批评,真的只是好奇),你会在哪里重载地址运算符?
  • @roe:在像 ATL::CComPtr (msdn.microsoft.com/en-us/library/ezzw7k98(VS.80).aspx) 这样有意义的类中。您经常使用它们而不是原始指针。您希望为 CComPtr 调用类似 HRESULT GetStuff( IInterface** ) 的函数,并且需要有一种方法来检索封装指针的地址或重载 operator&()
  • 快速浏览到标准中关于容器的章节后,我没有找到这样的说法。免责声明:我刚刚浏览过,如果不是粗体字母和/或句子的开头,我可能会错过它:)
  • @David:CopyConstructible 要求 (20.1.3) 指定 &t 的类型为 T* 并且“表示 T 的地址”。这在技术上并不禁止运算符重载,但确实禁止更改其行为。
  • @Mike:谢谢,当您浏览文档时会发生这种情况:)

标签: c++ stl operators operator-overloading


【解决方案1】:

在没有查看链接的情况下,我想boost::addressof() 中的技巧是在要求不要重载一元前缀& 以将对象保存在标准库的容器中之后发明的。

我隐约记得 Pete Becker(当时为 Dinkumware 的标准库实现工作)曾经说过,每个重载地址操作符并期望他们的标准库实现仍然工作的人都应该通过必须实现一个标准库来惩罚做这个。

【讨论】:

  • 这确实让人想知道为什么一开始就允许重载地址运算符,不是吗?
  • @MadKeithV:当为 C++“发明”运算符重载时,必须决定哪些运算符应该可重载,哪些不应该。由于当时没有任何经验——至少没有使用 C++——所以不得不猜测。事后看来,批评这些猜测很容易。 (虽然,因为它确实被使用过,有人会认为重载一元前缀& 是有用且有益的。)
【解决方案2】:

可能是因为仅仅禁止使用重载的 operator&() 类比创建 std::addressof() 函数并用它替换容器代码中 & 的每次使用更容易。

【讨论】:

  • VS2010 团队无论如何都在重新设计整个 STL。这不是争论。根据所提到的帖子,这是未定义的行为。 (-1)
  • VS2010团队是否指定了C++标准,我认为更多的是为什么标准是什么的问题?无论如何,另一个答案可能更好,因为它是历史事件。
【解决方案3】:

该标准于 1998 年完成,并在 2003 年进行了修复,而 boost::addressofdates to 2002 年初。

此外,尚不清楚addressof 是否是答案。 operator&() 的重载表明应该避免使用原始指针。 Allocator::address 成员提供了从 Allocator::referenceAllocator::pointer 的最佳接口,因此在一般理论上,您应该能够有效地引入 operator& 覆盖到其他行为良好的具有自定义分配器的类。

考虑到引用几乎完成了指针所做的所有事情,而分配器接口抽象了其他所有事情,因此应该不需要原始指针。

对库实施者的方便应该不是问题。 Allocator::pointer 定义不明确的语义是一个问题,而我目前在 C++0x 中所读到的内容并没有弄清楚这一点。

C++0x 从 CopyConstructible 中删除了对 operator& 的任何提及,而且根本不需要任何可构造的容器参数——用户可以坚持使用 emplace。甚至vector 也只需要 Destructible,尽管我想实际使用 inserterase 需要更多。

(请注意,严格来说,C++03 中不禁止重载。只是不允许更改内置函数的值或类型。)

【讨论】:

  • 标准于 1998 年定稿”于 1997 年。
猜你喜欢
  • 2012-01-19
  • 2018-01-01
  • 1970-01-01
  • 2020-12-26
  • 2012-04-09
  • 1970-01-01
  • 2018-04-06
  • 2010-11-23
  • 1970-01-01
相关资源
最近更新 更多