代码之家  ›  专栏  ›  技术社区  ›  S.S. Anne

重载减量运算符时使用的额外参数是什么?

  •  -1
  • S.S. Anne  · 技术社区  · 5 年前

    当我重载后减量运算符时,必须包含一个额外的参数:

    #include <iostream>
    
    template<class T>
    class wrap
    {
    public:
        bool operator >(T &&v)
        {
            return value > v;
        }
        T operator --(int v) // Remove 'int v' and you get a compilation error
        {
            return (value -= 1) + 1;
        }
        wrap(T v)
        {
            value = v;
        }
    private:
        T value;
    };
    
    int main(void)
    {
        wrap<int> i(5);
        while(i --> 0)
            std::cout << "Why do we need the extra argument?\n";
        return 0;
    }
    

    如果删除此看似不需要的参数,则会出现编译错误:

    test.cpp: In function ‘int main()’:
    test.cpp:26:13: error: no ‘operator--(int)’ declared for postfix ‘--’ [-fpermissive]
         while(i --> 0)
               ~~^~
    

    这个论点是用来干什么的?它的价值代表什么?

    2 回复  |  直到 5 年前
        1
  •  1
  •   scohe001    5 年前

    cppreference :

    这个 int 参数是用于区分运算符的前缀和后缀版本的伪参数。调用用户定义的postfix运算符时,该参数中传递的值始终为零,尽管可以通过使用函数调用符号调用该运算符来更改该值(例如。, a.operator++(2) operator++(a, 2) ).

    尽管我强烈建议不要使用这些显式调用的功能(对于其他人来说,这看起来非常奇怪)。

        2
  •  0
  •   Paul Evans    5 年前

    因为您使用的是后缀递减:

     while (i-- > 0)
    

    会减少 i 但返回原值:

    T operator--(int) // dummy int param for postfix
    {
        T temp = value;
        value -= 1;
        return temp;
    }
    

    假人 int 参数只是一个占位符,用于区分后缀和前缀减量:

    T operator--() // no param for prefix
    {
        value -= 1;
        return value;
    }
    
        3
  •  0
  •   Remy Lebeau    5 年前

    有两个独立但相关的重载 operator++ - pre-increment and post-increment . 两者都是可重写的。由于它们都具有相同的名称,所以C++的设计者必须决定一个语法,以便编译器区分它们。他们选择用假人 int post increment运算符上的参数。

    当您编写这样的代码时:

    wrap<int> i(5);
    ++i; // <-- calls i.operator++();
    

    编译器发出代码来调用无参数 operator++() .

    当您编写这样的代码时:

    wrap<int> i(5);
    i++; // <-- calls i.operator++(0);
    

    编译器发出代码来调用参数 operator++(int) ,通过 0 对于伪参数。

    这个 价值 参数的值是没有意义的,它的存在就足以让 操作员++ 因为它们有不同的签名而被单独重写。

    顺便说一下,同样的规则也适用于减量前后 operator-- 也。

        4
  •  0
  •   Peter    5 年前

    每一个批准的ANSI和ISO C++标准,以及每一个工作草案都描述了这一点,尽管精确的措辞在版本之间有所变化。

    例如,根据“工作草案,C++语言编程标准”,文件编号N4699,日期2017-03-21,第16.5.7节“递增和递减[O.Inc]”,PARA 1。

    用户定义的函数调用 operator++ 实现前缀和后缀 ++ 接线员。如果此函数是没有参数的非静态成员函数,或是只有一个参数的非成员函数,则定义前缀增量运算符 ++ 对于那种类型的对象。如果函数是具有一个参数的非静态成员函数(应为int类型)或具有两个参数的非成员函数(第二个参数 其中应为int类型),它定义后缀增量运算符 ++ 对于那种类型的对象。当使用 ++ 运算符,int参数的值为零。

    在前一段的末尾,有一个脚注134的参考,它说

    打电话 操作员++ 显式的,如 a.operator++(2) ,没有特殊属性:的参数 操作员++ 2 .

    在第1段之后,标准甚至提供了一个例子。

    [ 例子:

    struct X {
        X& operator++(); // prefix ++a
        X operator++(int); // postfix a++
    };
    
    struct Y { };
      Y& operator++(Y&); // prefix ++b
      Y operator++(Y&, int); // postfix b++
    
    void f(X a, Y b) {
        ++a; // a.operator++();
        a++; // a.operator++(0);
        ++b; // operator++(b);
        b++; // operator++(b, 0);
    
        a.operator++(); // explicit call: like ++a;
          a.operator++(0); // explicit call: like a++;
          operator++(b); // explicit call: like ++b;
          operator++(b, 0); // explicit call: like b++;
    }
    

    — 结束示例 ]

    第2段接着说

    前缀和后缀递减运算符 -- 以类似的方式处理。

    推荐文章