简体   繁体   English

前缀/后缀增量运算符

[英]Prefix/Postfix increment operators

I'm wanting to make sure I understand pass-by-value vs pass-by-reference properly. 我想确保我理解按值传递和正确传递。 In particular, I'm looking at the prefix/postfix versions of the increment ++ operator for an object. 特别是,我正在查看对象的increment ++运算符的前缀/后缀版本。

Let's suppose we have the following class X : 假设我们有以下类X

class X{
private:
    int i;
public:
 X(){i=0;}
 X& operator ++ (){ ++i; return *this; } //prefix increment

 X operator ++ (int unused){ //postfix increment
  X ret(*this);
  i++;
  return ret;
 }

 operator int(){ return i; } //int cast
};

First of all, have I implemented the prefix/postfix increment operators properly? 首先,我是否正确实现了前缀/后缀增量运算符?

Second, how memory-efficient is the postfix operator, compared to the prefix operator? 第二,与前缀运算符相比,后缀运算符的内存效率如何? Specifically how many X object copies are created when each version of the operator is used? 具体来说,当使用每个版本的运算符时,会创建多少个X对象副本?

An explanation of exactly what happens with return-by-reference vs return-by-value might help me understand. 准确地解释通过引用返回和按值返回会发生什么可能有助于我理解。


Edit: For example, with the following code... 编辑:例如,使用以下代码...

X a;
X b=a++;

...are a and b now aliases? ... a和b现在是别名吗?

It is more idiomatic to call the prefix increment of the object itself in the postfix increment: 在后缀增量中调用对象本身的前缀增量更为惯用:

X operator++(int)
{
    X copy(*this);
    ++*this;         // call the prefix increment
    return copy;
}

The logic of incrementing an X object is thus solely contained inside the prefix version. 因此,递增X对象的逻辑仅包含在前缀版本中。

This is a correct implementation. 这是一个正确的实现。 It is typical that a postfix operator will be worse on performance because you have to create another copy before doing the increment (and this is why I've gotten in the habit of always using prefix unless I need something else). 通常情况下,后缀运算符的性能会更差,因为您必须在执行增量之前创建另一个副本(这就是为什么我习惯于始终使用前缀,除非我需要其他东西)。

With return-by-reference, you're returning an l-value reference to the current object. 通过引用返回,您将返回对当前对象的l值引用。 The compiler would typically implement this by returning the address of the current object. 编译器通常会通过返回当前对象的地址来实现它。 This means that returning the object is as simple as returning a number. 这意味着返回对象就像返回一个数字一样简单。

However, with return-by-value, a copy must be done. 但是,按值返回,必须完成复制。 This means there's more information to copy over during the return (instead of just an address) as well as a copy constructor to call. 这意味着在返回期间(而不仅仅是地址)复制更多信息以及要调用的复制构造函数。 This is where your performance hit comes in. 这就是您的性能受到影响的地方。

The efficiency of your implementation looks on-par with typical implementations. 您的实施效率与典型实施相当。

EDIT: With regards to your addendum, no, they are not aliases. 编辑:关于你的附录,不,它们不是别名。 You have created two separate objects. 您已创建两个单独的对象。 When you return by value (and when you created a new object from within the postfix increment operator) this new object is placed in a distinct memory location. 按值返回时(以及从后缀增量运算符中创建新对象时),此新对象将放置在不同的内存位置。

However, in the following code, a and b are aliases: 但是,在以下代码中,a和b 别名:

 int a = 0;
 int& b = ++a;

b is an address which references a. b是引用a的地址。

Your operators are implemented correctly. 您的操作员已正确实施。

In the prefix operator, no copies of X are made. 在前缀运算符中,不会生成X的副本。

In the postfix operator, one copy is made for ret, and potentially another copy is made when returning from the function, but all compilers will elide this copy. 在后缀运算符中,为ret做了一个副本,从函数返回时可能会生成另一个副本,但是所有编译器都会忽略此副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM