为什么后增量需要复制而预增量不需要

时间:2015-06-19 15:31:11

标签: c++ increment post-increment pre-increment

我知道这个问题已经多次讨论过了,但我找不到一个解释为什么在后增量操作时需要复制的帖子。

从stackoverflow回复引用:

int j = i++; // j will contain i, i will be incremented.
int j = ++i; // i will be incremented, and j will contain i+1.

当考虑后/前增量的定义时,这是完全有意义的。很多时候,在比较前/后增量的性能时,可以说后增量需要复制,增加它并返回副本,而预增量只增加值而不创建副本。

虽然已经在数十篇帖子中对性能进行了比较,但我真的找不到为什么在后增量的情况下必须制作副本的任何解释。为什么不返回旧值然后将变量的值增加1(或者操作符重载方式),而不是创建新对象并返回该对象。

3 个答案:

答案 0 :(得分:8)

差异是someval++返回增量前someval的内容,为此,您需要记住someval与副本的关系。如果原始值没有存储在某个位置,如果更新原始值,您还会如何返回原始值?

答案 1 :(得分:6)

将预增量和后增量运算符视为标准函数:

// ++i
int pre_increment(int &i) {
    i = i + 1;
    return i;
}

// i++
int post_increment(int &i) {
    int original_i = i;
    i = i + 1;
    return original_i;
}

这可以帮助您理解为什么在第二种情况下(i ++),您必须在执行增量之前执行该值的副本。

答案 2 :(得分:2)

我很难说出编译器如何优化预增量和后增量运算符,以便不必对原始类型进行复制。

我可以展示如何为后增量运算符的用户定义类型创建副本。

让我们简单地看一下std::vector::iterator

假设迭代器存储索引,除了其他东西。

struct iterator
{
   size_t index;

   iterator operator++(int )
   {
      iterator copy = *this;
      this->index++;
      return copy;
   }
 };

在这种情况下,不能先返回*this然后递增索引。创建副本,递增this的索引,然后返回副本允许我们保留该操作的语义。