Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 运算符的返回值++;_C++ - Fatal编程技术网

C++ 运算符的返回值++;

C++ 运算符的返回值++;,c++,C++,我有下面的代码被破坏了。我可以通过修改代码中的某一行来修复它(参见注释)。问题的原因是什么 #include <iostream> using namespace std; class Number{ public: int n; Number(int a):n(a){} //when I change the following to //friend Number& operator++(Number& source, int

我有下面的代码被破坏了。我可以通过修改代码中的某一行来修复它(参见注释)。问题的原因是什么

#include <iostream>
using namespace std;

class Number{
public:
    int n;
    Number(int a):n(a){}

    //when I change the following to
    //friend Number& operator++(Number& source, int i)
    //then it compiles fine and correct value is printed
    friend Number operator++(Number& source, int i){
        ++source.n;
        return source;
    }
};

int main() {

    Number x(5);
    x++++; //error: no 'operator++(int)' declared for postfix '++' [-fpermissive]
    cout<<x.n;

    return 0;
}
#包括
使用名称空间std;
班号{
公众:
int n;
数字(inta):n(a){
//当我将以下内容更改为
//朋友编号和运算符++(编号和来源,int i)
//然后,它编译出精细的值,并打印出正确的值
朋友编号运算符++(编号和源,int i){
++资料来源:n;
返回源;
}
};
int main(){
数字x(5);
x++++;//错误:没有为后缀“++”[-fpermissive]声明“运算符++(int)”

cout您正在通过写入
x++
来增加内部
运算符+++
的返回值。这意味着如果该运算符的返回值不可修改,则代码将无法编译


因此,如果将其声明为返回
Number
而不是
Number&
,则不能对其进行修改(函数的返回值是临时值,而不是左值,除非它是引用,因此外部运算符+++通过(非常量)引用获取它,不能将其绑定到通过值返回的对象).

尝试将第二个
++
应用于第一次调用返回的临时对象。但是,操作数必须通过引用传递,并且不能将临时对象绑定到非常量左值引用

您可能不想“修复”这个问题,因为几乎没有理由修改这样的临时值。但是,您应该在递增之前返回该值的副本,以提供预期的递增后行为


前缀运算符应该返回一个引用,该引用可以很好地绑定到另一个引用,以便
++++x;
能够按预期工作。

您尝试执行的操作非常不寻常。增量后通常返回一个表示增量前对象的右值(与pre-increment相反,pre-increment首先递增对象,然后返回对象本身,作为左值)。出于无法解释的原因,您基本上是在尝试使post-increment的行为与pre-increment相同

通常,您会这样做:

class Number {
  int n;
public:
  // Pre-increment
  Number& operator++() {
    ++n;
    return *this;
  }
  Number operator++(int) {
    Number temp = *this;  // capture old value
    ++(*this);
    return temp;
  }
};
根据这个定义,
x++
不会编译,但是当
x
int
时,它也不会编译:这没有多大意义

无论如何,它不适合您的原因如下。
x++
被解释为

operator++(operator++(x, 0), 0)

内部的
operator++
调用返回一个临时的
Number
对象。外部的
operator++()
需要一个类型为
Number&
的参数,但非常量引用不能绑定到临时引用。当您更改声明,使
操作符+
返回
Number&
-一个左值时,可以将此返回值愉快地传递给外部
操作符+
调用。

让我们从观察你也不能像这样为
int
链接postincrement操作符

在我解决这个问题之前,让我建议不要写这样不直观的代码。从现在起一年后,有人将不得不阅读你的程序,你想让它尽可能容易地阅读

考虑到
x++
实际上类似于
operator++(operator++(x,int),int)
,所以现在发生的是第一个
operator++
按值返回(这导致返回一个未命名的临时值)。这个未命名的临时值不能绑定到第二个(外部)的非常量引用参数调用,方法查找失败


最后请注意,您的实现实际上并没有实现后缀增量:它实现前缀增量或者修复实现以返回未修改的值。

为什么这会让您感到惊讶?想想postfix
operator++
的语义,您返回什么,您尝试做什么,以及您尝试向谁做。为什么您的代码中需要
friend
。@triclosan这里没有必要,但假设他有一个private成员并想要一个全局函数而不是成员重载?@triclosan,因为运算符++是一元函数,如果它是成员函数,它将只有一个参数(int)。我相信这个有两个参数的版本不是成员函数(即使它是在类中定义的)因此需要朋友。问题是后缀增量不能通过引用返回,因为它将返回已经增加的值!@MarkB:所以不能;我没有正确地阅读代码。他为什么要从
operator++
a
friend
开始?@NikBougalis:因为,当你不编写玩具类时作为演示,您可能希望数据成员是私有的。尽管它可以是成员,但如果您愿意的话。@NikBougalis:将其设置为非成员的一个很好的理由是,如果您编写
x++++;
,您将得到错误而不是意外的结果,如问题所示。您可以只修改类类型的临时值/r值很好。问题是,如果按值返回,则无法链接运算符,因为运算符通过非常量引用获取第一个参数。@jrok(我实际上怀疑是这样的,但我不确定。)那么,如果我添加了“因此外部
运算符+++
,它通过(非常量)获取,这是否正确引用,无法将其绑定到由值“”返回的对象上?那很好,我想。@jrok谢谢你的建议!现在,准备一些可怕的事情:!(当然没有用例,但仍然:/)PS:你收到我的了吗?我想给定你的代码,
x++
实际上会编译,因为
x.operator++(0)。operator++(0)
格式正确。您可以通过声明成员
Number operator++(int)&
(但仅限于最近的gcc/clang版本)来解决此问题