【问题标题】:Is operator-> "chained" for pointers? [duplicate]operator-> 是否为指针“链接”? [复制]
【发布时间】:2011-06-22 20:04:45
【问题描述】:

可能重复:
Overloading operator ->

嗨,

我看到operator->() 在评估后被链接(重新应用),例如:

struct Bar
{
  Bar() : m_str("Hello world!") {}
  const string* operator->() const { return &m_str; }
  string m_str;
};

struct Foo
{
  const Bar& operator->() const { return m_bar; }
  Bar m_bar;
};

int main()
{
  Foo f;
  cout << f->c_str() << endl;
  return 0;
}

工作得很好,这需要评估三个operator-&gt;() - Foo::operator-&gt;()Bar::operator-&gt;() 和常规指针解析。

但它不适用于中间的指针 - 如果 Foo::operator-&gt;() 返回指向 Bar 的指针而不是引用,它不会编译。例如,auto_ptr&lt;auto_ptr&lt;string&gt;&gt; 也是如此。

它是否特定于非重载operator-&gt;(),所以它只应用一次并且不会导致链接? 是否可以在不使用(*ptr2)-&gt; ... 的情况下使下面的代码工作?

int main()
{
  string s = "Hello world";
  auto_ptr<string> ptr1(&s);
  auto_ptr<auto_ptr<string> > ptr2(&ptr1);
  cout << ptr1->c_str() << endl; // fine
  cout << ptr2->c_str() << endl; // breaks compilation
}

谢谢!

【问题讨论】:

  • 重复Overloading operator -> [AndreyT 的回答解释了operator-&gt; 的行为以及“链接”是如何发生的。]
  • @James 我倾向于保持开放,因为问题的措辞不同。它可以帮助其他人找到答案。
  • @Judge:一个封闭的问题不会被自动删除,像这样一个问得很好的问题也不会被删除;该问题仍然存在并且可以搜索。
  • 谢谢!然后似乎无法覆盖 operator-> for 指针,因此第二个问题无能为力。对吗?
  • 需要注意的是,这种方式使用auto_ptr会导致函数结束时销毁变量时发生各种可怕的事情。

标签: c++ operator-keyword method-chaining


【解决方案1】:

C++98 标准§13.5.6/1“类成员访问”:

如果 T::operator-&gt; 存在并且如果运算符在重载解析机制 (13.3) 的最佳匹配函数中选择,则表达式 x-&gt;m 被解释为 x 类型为 T 的类对象 (x.operator-&gt;())-&gt;m .

这在实践中意味着当x 是一个指针时,你不会得到链接;然后,您只需获得内置的operator-&gt;(即x-&gt;mx,指针转换为(*x).m)。

但是当x是类类型T的对象时,就可以得到链接效果。因为那么(x.operator-&gt;())-&gt;m 的解释可能是(x.operator-&gt;()) 本身是某个类的对象,比如类U。因此第二个-&gt; 可以解析为U::operator-&gt;,以此类推,如果结果再次是类类型对象……

就像,在你的例子中,Foo::operator-&gt; 产生(引用)一个 Bar 类的对象,它确实定义了一个 operator-&gt;

但是当operator-&gt; 返回一个指针时,例如std::auto_ptr&lt;T&gt;::operator-&gt; 可以,那么它只是使用了内置的operator-&gt;

顺便说一句,链接可以用于实际上防止某人不恰当地使用deletestd::auto_ptr 不会那样做。而且我从未见过这样做过。

但是在 [comp.lang.c++.moderated] 中曾经有过一个关于如何防止无意中delete 由智能指针管理的原始指针的长时间讨论线程,这是讨论的一种可能性。

干杯&hth。

【讨论】:

    【解决方案2】:

    您的第一个示例有效的原因是您返回了引用而不是指针。该运算符通常是无效的,除非它被重载。因此,编译器必须沿链执行重载函数。但是,在 auto_ptr 的情况下,您实际上会返回一个真正的指针,并且会为常规指针调用默认的 operator -&gt;

    请参阅Overloading operator -> 问题了解更多详情。

    【讨论】:

    • 感谢您的回答。我一直在寻找方法来简化迭代 vector > 和类似内容的代码。似乎唯一的选择是将vector的(任何容器)迭代器专门用于shared_ptr(其他一些智能ptr),这是不可接受的。
    【解决方案3】:

    不,它不可能工作。如果你可以为string * 重载operator -&gt;,你就可以让它工作。但是operator -&gt; 已经定义了所有指针类型。因此,就像您不能为原始数字类型重载 + 一样,您也不能为任何指针类型重载 operator -&gt;

    即使你可以,编译器怎么知道递归应该何时结束?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-26
      • 2012-03-27
      • 1970-01-01
      • 2010-11-02
      • 2013-11-28
      • 1970-01-01
      • 2018-09-12
      相关资源
      最近更新 更多