我知道这个问题已经多次讨论过了,但我找不到一个解释为什么在后增量操作时需要复制的帖子。
从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(或者操作符重载方式),而不是创建新对象并返回该对象。
答案 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
的索引,然后返回副本允许我们保留该操作的语义。