【问题标题】:const overloaded operator[] function and its invocationconst 重载 operator[] 函数及其调用
【发布时间】:2011-04-23 03:53:49
【问题描述】:

我在类array 中定义了两个版本的重载operator[] 函数。 ptr 是指向 array 对象的第一个元素的指针。

int& array::operator[] (int sub) {  
   return ptr[sub];
} 

int array::operator[] (int sub) const { 
  return ptr[sub];
}

现在,如果我定义一个 const 对象integer1,则只能调用第二个函数.....但是如果我创建一个非常量对象然后调用如下:

cout << "3rd value is" << integer1[2];

这里调用了哪个函数?

【问题讨论】:

  • 对于const 对象或访问路径,调用const 函数。否则,将调用非常量。 array 可能不是一个好的类名选择,因为在新的 C++11 标准中有一个 std::array 模板。
  • 只是一个观察。最好从 const 版本返回 const 引用。示例见 std::vector::operator[] 的声明。

标签: c++ operator-overloading


【解决方案1】:

在您的第二个示例中,将调用非常量版本,因为不需要转换,并且不需要转换的调用比需要转换的调用更好。

然而,最终,您在这里遇到了一个基本问题:您真正想要的是根据您将对象用作右值还是左值而改变的行为,而const 并没有真正做到这一点。为了使其正常工作,您通常希望返回一个代理对象,并为代理对象重载 operator=operator T

template <class T>
class myarray { 
    T *ptr;

    class proxy { 
        T &val;
        proxy &operator=(proxy const &p); // assignment not allowed.
    public:
        proxy(T &t) : val(t) {}
        operator T() const { return val; }
        proxy &operator=(T const&t) { val = t; return *this; }
    };

    proxy const operator[](int sub) const { return proxy(ptr[sub]); }
    proxy operator[](int sub) { return proxy(ptr[sub]); }
    // obviously other stuff like ctors needed.
};

现在我们得到了正常的行为——当/如果我们的array&lt;int&gt;(或任何类型)是常量,我们的operator[] const将被使用,它会给出一个const proxy。由于它的赋值运算符是 not const,因此尝试使用它们会失败(不会编译)。

OTOH,如果原始 array&lt;int&gt; 不是 const,我们将获得一个非常量代理,在这种情况下,我们可以同时使用 operator Toperator=,并且能够读取和写入值在array&lt;int&gt;.

【讨论】:

  • 这和原来的解决方案有同样的问题——如果你想做,比如说object[1].swap(object[2]);,首先,语法会是错误的,因为proxy&lt;T&gt;没有定义那个函数,即使@ 987654334@ 确实如此,其次,您不必要地复制 object[2],因为您不返回引用 - 即使 proxy 是非常量。
  • 棺材是什么转换,你说的是const版本
  • @avinash:从myarray &amp; 转换为myarray const &amp;。它可以隐式完成,但仍然不如不进行转换。
【解决方案2】:

您的 const 版本应该返回 const int&amp; 而不是 int,以便两个函数之间的语义完全相同

一旦你这样做了,使用哪一个并不重要。如果由于您的对象具有 const 上下文而必须使用 const 版本,那么它将是……而且这并不重要,因为您没有尝试修改任何内容。否则,它将使用非const 版本...但效果相同。

【讨论】:

  • 我不同意。与int 相比,我认为返回const int&amp; 没有任何好处。
  • @FredOverflow:对称就是一切。而且我不希望能够在const 对象上修改operator[] 的结果(即使它只是一个副本):那会产生误导。
  • 您不能修改按值返回标量的函数的结果。你得到一个,而不是一个临时对象。
  • @FredOverflow:什么?如果我有T const obj; 并且我可以写obj[3] = 4;,因为我使用的是按值返回的op[],那么这很令人困惑。我希望op[] 返回ref-to-const,这样我就无法执行该任务。
  • 我支持@Fred。就像function parameters 一样:除非它们是按值传递的内置函数,否则您通过 const 引用传递。 built-in 的临时对象与 const 引用几乎没有可检测的差异(两者都无法修改,都绑定到 const ref),并且返回它们可能比返回引用更有效。所以为了对称(带函数参数),operator[]() constshould return built-ins by value.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-18
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多