为什么post-increment需要复制而pre-increment不需要
Why post-increment needs to make a copy while pre-increment does not
我知道这个问题已经讨论过好几次了,但是我找不到 post 来解释为什么在 post-increment 操作的情况下需要制作副本。
引用来自 Whosebug 的回复:
int j = i++; // j will contain i, i will be incremented.
int j = ++i; // i will be incremented, and j will contain i+1.
当考虑 post/pre 增量的定义时,这完全有意义。很多时候比较pre/post增量的性能时说post增量需要做一个副本,增量它和return副本而预增量只是增加价值而不创造复印件。
虽然性能对比了几十post秒,但我实在找不到任何解释为什么在post增量的情况下必须进行复制。为什么它不 return 旧值然后将变量的值递增一个(或者运算符重载的方式),而不是创建一个新对象然后 return 那个。
不同之处在于 someval++
returns 增量之前的 someval
是什么,要做到这一点,您需要记住副本中的 someval
是什么。如果原始值未存储在某处,您还可以如何在更新原始值时 return 原始值?
将预递增和post-递增运算符视为标准函数:
// ++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++) 中,您必须在执行递增之前执行值的复制。
我很难说编译器如何优化预递增和 post-递增运算符,以便不必在基本类型上进行复制。
我可以展示如何为 post-增量运算符的用户定义类型制作副本。
让我们简单地看一下std::vector::iterator
。
假设迭代器除了存储其他内容外,还存储一个索引。
struct iterator
{
size_t index;
iterator operator++(int )
{
iterator copy = *this;
this->index++;
return copy;
}
};
在这种情况下,不可能先return *this
然后递增索引。创建副本,增加 this
的索引,然后 returning 副本允许我们保留该操作的语义。
我知道这个问题已经讨论过好几次了,但是我找不到 post 来解释为什么在 post-increment 操作的情况下需要制作副本。
引用来自 Whosebug 的回复:
int j = i++; // j will contain i, i will be incremented.
int j = ++i; // i will be incremented, and j will contain i+1.
当考虑 post/pre 增量的定义时,这完全有意义。很多时候比较pre/post增量的性能时说post增量需要做一个副本,增量它和return副本而预增量只是增加价值而不创造复印件。
虽然性能对比了几十post秒,但我实在找不到任何解释为什么在post增量的情况下必须进行复制。为什么它不 return 旧值然后将变量的值递增一个(或者运算符重载的方式),而不是创建一个新对象然后 return 那个。
不同之处在于 someval++
returns 增量之前的 someval
是什么,要做到这一点,您需要记住副本中的 someval
是什么。如果原始值未存储在某处,您还可以如何在更新原始值时 return 原始值?
将预递增和post-递增运算符视为标准函数:
// ++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++) 中,您必须在执行递增之前执行值的复制。
我很难说编译器如何优化预递增和 post-递增运算符,以便不必在基本类型上进行复制。
我可以展示如何为 post-增量运算符的用户定义类型制作副本。
让我们简单地看一下std::vector::iterator
。
假设迭代器除了存储其他内容外,还存储一个索引。
struct iterator
{
size_t index;
iterator operator++(int )
{
iterator copy = *this;
this->index++;
return copy;
}
};
在这种情况下,不可能先return *this
然后递增索引。创建副本,增加 this
的索引,然后 returning 副本允许我们保留该操作的语义。