增量,前增量和后增量

时间:2012-02-15 17:17:31

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

请帮我解决这个问题。表达式后面的步骤是:

//Expression
offSpring1[m1++] = temp1;
  

//步骤:

     

1.-增加m1

     

2.-将temp1指定给offSpring

我一直认为括号内的表达式是第一个要完成的。但现在我很困惑。所以,如果写这个:

//Expression
offSpring1[++m1] = temp1;
//Steps would be:

1.- assign temp1 to offSpring
2.- increment m1

如果步骤与第一步相同,那么i ++和++ i之间的区别是什么?

10 个答案:

答案 0 :(得分:8)

int i = 0;
std::cout << i++ << std::endl;
std::cout << i << "\nreset" << std::endl;
i = 0;
std::cout << ++i << std::endl;
std::cout << i << std::endl;

输出:

0
1
reset
1
1

i++返回当前表达式中的值,然后递增变量。 ++i将递增变量,然后返回要在当前表达式中使用的值。

答案 1 :(得分:3)

offSpring1[m1++] = temp1;

offSpring1[m1] = temp1;
m1 += 1;

offSpring1[++m1] = temp1;

m1 += 1;
offSpring1[m1] = temp1;

答案 2 :(得分:1)

只需运行这两个不同的测试程序,即可了解后增量和预增量运算符之间的区别

对于++ i(预增量)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[++m1] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

在第一个中你将获得10作为offSpring [m1]的值。 为什么?因为这是预增量运算符,这意味着第一个m1递增,其余的得到评估。

对于i ++(后增量)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[m1++] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

在第二个因为使用了后增量运算符,你将获得一个0值,因为你首先将10分配给offSpring [m1],然后m1增加。

答案 3 :(得分:1)

  • j = ++ii = i+1; j = i;
  • 相同
  • j = i++j = i; i = i+1;
  • 相同

答案 4 :(得分:0)

offSpring1[m1++] = temp1;没做你说的话。

  1. 指定temp_m1 = m1。
  2. 增量m1。
  3. index offSpring1[temp_m1]
  4. temp1分配到索引值。
  5. 另一方面,offSpring1[++m1] = temp1;的工作原理如下:

    1. 增量m1。
    2. index offSpring1[m1]
    3. temp1分配到索引值。

答案 5 :(得分:0)

第一个的描述是对第二个的正确描述。第一个的正确描述非常相似,您只需要在其他人之前添加“复制当前值m1”步骤。

但是如果m1具有基本类型,那么这里确实缺少序列点。规则在C ++ 03和C ++ 11之间有所改变。

如果m1具有用户定义的类型,则涉及影响排序的函数调用。


此代码

offSpring1[m1++] = temp1;

执行以下操作(如果m1是基本类型):

auto const old_m1(m1);
auto const new_m1(old_m1 + 1);
auto& lhs(offSpring[old_m1]);
parallel { lhs = temp1; m1 = new_m1; }

此代码

offSpring1[++m1] = temp1;

完全相同,只是lhs使用new_m1代替old_m1绑定。

在任何一种情况下,都未指明在lhs之前或之后是否写入m1

如果m1不是原始类型,它看起来更像是:

auto const& index = m1.operator++(0); // one argument
auto& lhs = offSpring.operator[](index);
lhs = temp1;

VS

auto const& index = m1.operator++(); // no arguments
auto& lhs = offSpring.operator[](index);
lhs = temp1;

在这两种情况下,m1的更改肯定是在写入lhs之前进行的。

答案 6 :(得分:0)

即使在第一个示例中第一个要计算后缀增量,它的值也是增量变量的原始值。

offSpring1[m1++] = temp1;

因此,即使m1在数组idexing之前递增,temp1的值也会在m1 - 1位置指定。

答案 7 :(得分:0)

它恰恰与你描述的相反:

offSpring1[m1++] = temp1与...相同 offSpring[m1] = temp1; m1 = m1 + 1;

OffSpring1[++m1] = temp1与...相同 m1 = m1 + 1; OffSpring1[m1] = temp1;

在评估表达式之前,前缀表示法会递增 在评估表达式

之后,后缀表示法递增

答案 8 :(得分:0)

表达式(或子表达式)有两个方面:它的值, 及其副作用。 i ++的值是i的值;该 ++ i的值是值i + 1,转换为i的类型。 这是表达式中使用的值。两者的副作用是 增加变量i。这可能发生在之后的任何时间 前一个序列点和下一个序列点之前。假设i是全球性的 变量,你写了类似的东西:

i = 0;
f()[i ++] = g();
f()[++ i] = g();

该标准没有说明if()的值是否为g()f()是增量之前或之后。在任何情况下。 所有标准都表示增量的效果会 在完整表达开始后发生(但也许是作为 完整表达式中的第一件事)并在它结束之前。 (然后 它们不会与函数调用交错,因此如果i 读取{{1}}两次,保证看到相同的值。)

答案 9 :(得分:0)

不幸的是,在那里发布的那两个代码段中,没有保证评估顺序。如果你的表达不合适,可能会发生或多或少的事情。

首先介绍a ++和++之间的区别a:

  • a ++将增加a但使用它的表达式将在增量
  • 之前看到a的值
  • ++ a将增加a,使用它的表达式将看到递增的值。
  • 列表项

buffer[a++] = b;

编译器可以决定在表达式中的任何位置执行++。因此,如果'b'实际上是涉及a的表达式,则可以在不同的编译器上获得不同的结果。以下两个都是有效的:

  • 获取a;
  • 的值
  • 增加一个
  • 找出缓冲区[旧值]指向
  • 的位置
  • 评估b
  • store b

或者

  • 评估b;
  • 找出缓冲区[a]指向
  • 的位置
  • store b
  • 增加一个

如果'b'碰巧涉及a,那么这2个实现会产生不同的结果。两者都有效。