C++在前缀重载中返回引用变量

发布于 2024-12-09 02:08:04 字数 1761 浏览 0 评论 0原文

当我发现的所有代码都显示在重载前缀运算符时返回引用变量时,我感到很困惑。我浏览了 parashift.com 常见问题解答(http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14),但不清楚,尽管它说会很清楚当你读到它的时候。我将他们的示例改编成一个无意义的、毫无意义的小程序来测试。

#include<iostream>
using namespace std;

class Number {
   public:
      Number& operator++ ();    // prefix ++
      Number  operator++ (int); // postfix ++
      int value() { return value_; }
      void setValue(int value) { value_ = value; }
   private:
      int value_;
};

Number& Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ (int unused) {
   Number temp;
   temp.setValue(value_);
   ++value_;
   return temp;
}

int main()
{
   Number someNum;
   someNum.setValue(20);
   cout << "someNum : " << someNum.value() << "\n";
   someNum++;
   ++someNum;
   cout << "someNum : " << someNum.value() << "\n";
   return 0;
}

问题是,如果我只是将其声明为 Number 对象,就像这样:

#include<iostream>
using namespace std;

class Number {
   public:
      Number operator++ ();    // prefix ++
      Number  operator++ (int); // postfix ++
      int value() { return value_; }
      void setValue(int value) { value_ = value; }
   private:
      int value_;
};

Number Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ (int unused) {
   Number temp;
   temp.setValue(value_);
   ++value_;
   return temp;
}

int main()
{
   Number someNum;
   someNum.setValue(20);
   cout << "someNum : " << someNum.value() << "\n";
   someNum++;
   ++someNum;
   cout << "someNum : " << someNum.value() << "\n";
   return 0;
}

我假设我只是需要更好地理解引用变量。谁能简单地解释一下为什么前缀运算符应该被编码为返回引用变量?

I am confused when all the code I find shows returning a reference variable when overloading the prefix operator. I went through the parashift.com FAQ (http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14) and it isn't clear, even though it says it WILL be clear when you read it. I adapted their example into a nonsensical, pointless little program to test.

#include<iostream>
using namespace std;

class Number {
   public:
      Number& operator++ ();    // prefix ++
      Number  operator++ (int); // postfix ++
      int value() { return value_; }
      void setValue(int value) { value_ = value; }
   private:
      int value_;
};

Number& Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ (int unused) {
   Number temp;
   temp.setValue(value_);
   ++value_;
   return temp;
}

int main()
{
   Number someNum;
   someNum.setValue(20);
   cout << "someNum : " << someNum.value() << "\n";
   someNum++;
   ++someNum;
   cout << "someNum : " << someNum.value() << "\n";
   return 0;
}

The problem is, it works if I just declare it as a Number object as well like so:

#include<iostream>
using namespace std;

class Number {
   public:
      Number operator++ ();    // prefix ++
      Number  operator++ (int); // postfix ++
      int value() { return value_; }
      void setValue(int value) { value_ = value; }
   private:
      int value_;
};

Number Number::operator++ () {
   ++value_;
   return *this;
}

Number Number::operator++ (int unused) {
   Number temp;
   temp.setValue(value_);
   ++value_;
   return temp;
}

int main()
{
   Number someNum;
   someNum.setValue(20);
   cout << "someNum : " << someNum.value() << "\n";
   someNum++;
   ++someNum;
   cout << "someNum : " << someNum.value() << "\n";
   return 0;
}

I assume I simply need a better understanding of reference variables. Can anyone explain simply why the prefix operator SHOULD be coded as returning a reference variable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

荒芜了季节 2024-12-16 02:08:04

之间的区别

Number& Number::operator++ () {
   ++value_;
   return *this;
}

:和

Number Number::operator++ () {
   ++value_;
   return *this;
}

在于,当您使用第一个代码时,以下表达式:

++(++(++someNum)); 

someNum 递增三次。请参阅此处的输出: http://ideone.com/y9UlY

但是,当您使用第二个时,此

++(++(++someNum));

值会增加someNum 仅一次!!请参阅此处的输出: http://ideone.com/eOLdj

这是因为当您从 operator++(),第二个和第三个 ++ 调用同一个名为 someNum 的对象,因此,它始终递增同一个对象。但是,当您按值返回时,第二个和第三个 ++ 会调用从 operator++() 返回的临时对象。因此,第二次和第三次调用不会增加 someNum,而是增加在表达式末尾被销毁的临时对象。

现在,如果临时对象被销毁,为什么还要创建呢?毕竟,它的预自增运算符意味着临时对象和原始对象将具有相同的值。因此,好的设计决策是,在定义预自增运算符时按引用返回,以避免创建临时值,并提高性能。

The difference between :

Number& Number::operator++ () {
   ++value_;
   return *this;
}

and

Number Number::operator++ () {
   ++value_;
   return *this;
}

is that, when you use the first code, the following expression:

++(++(++someNum)); 

increments someNum THRICE. See the output here: http://ideone.com/y9UlY

However, when you use the second one, this

++(++(++someNum));

increments someNum just ONCE!! See the output here: http://ideone.com/eOLdj

It is because when you return the reference from operator++(), the second and third ++ invokes on the same object called someNum and therefore, it increments the same object, all the times. But when you return by value, the second and third ++ invokes on the temporary object which you returned from operator++(). Hence, the second and third call doesn't increment someNum, instead it increments the temporary objects which get destroyed at the end of the expression.

Now if the temporary objects get destroyed, why create then in the first place? After all, its pre-increment operator, which means the temporary and the original object will have the same value. So the good design decision is, return by reference when defining pre-increment operator, to avoid creating temporary, and improve performance.

故事未完 2024-12-16 02:08:04

首先,存在效率问题。您正在创建该类的新实例,以便无缘无故地返回它。

其次,还有语义问题。您的代码调用空构造函数或复制构造函数来创建临时对象,然后析构临时对象。如果它具有不恰当的语义,那么该代码实际上并不起作用,只是看起来起作用了。

第三,代码返回错误的内容。考虑:++foo.do_something();。通过您的代码,我们在临时对象上调用“do_something”。我们想要在预递增的 foo 上调用 do_something()

First, there's an efficiency issue. You are creating a new instance of the class in order to return it for no reason.

Second, there's the semantic issue. Your code invokes the empty constructor or the copy constructor to make the temporary and then destructs the temporary. If that has semantic meaning that's inappropriate, then the code doesn't really work, it just appears to.

Third, the code returns the wrong thing. Consider: ++foo.do_something();. With your code, we call 'do_something' on the temporary object. We wanted to call do_something() on the pre-incremented foo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文