1

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

//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 有什么区别?

4

10 回答 10

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将递增变量,然后返回要在当前表达式中使用的值。

于 2012-02-15T17:21:12.487 回答
4
offSpring1[m1++] = temp1;

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

offSpring1[++m1] = temp1;

m1 += 1;
offSpring1[m1] = temp1;
于 2012-02-15T17:23:19.557 回答
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 递增。

于 2012-02-15T17:23:57.987 回答
1
  • j = ++i是相同的i = i+1; j = i;
  • j = i++是相同的j = i; i = i+1;
于 2012-02-15T17:26:34.177 回答
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_m1old_m1

无论哪种情况,都未指定lhs是写入之前还是之后m1

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

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

对比

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

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

于 2012-02-15T17:24:04.157 回答
0

即使后缀增量是第一个在您的第一个示例中被评估的值,它的值是被增量变量的原始值。

offSpring1[m1++] = temp1;

因此,即使 m1 在数组索引之前递增, 的值temp1也会分配在 position m1 - 1

于 2012-02-15T17:24:06.750 回答
0

它的工作原理与您描述的完全相反:

offSpring1[m1++] = temp1是相同的 offSpring[m1] = temp1; m1 = m1 + 1;

OffSpring1[++m1] = temp1是相同的 m1 = m1 + 1; OffSpring1[m1] = temp1;

前缀符号在计算表达式之前递增 后缀符号在计算表达式之后递增

于 2012-02-15T17:24:16.357 回答
0

offSpring1[m1++] = temp1;不按你说的做。

  1. 分配 temp_m1 = m1。
  2. 增加 m1。
  3. 指数offSpring1[temp_m1]
  4. 分配temp1到索引值。

另一方面offSpring1[++m1] = temp1;是这样工作的:

  1. 增加 m1。
  2. 指数offSpring1[m1]
  3. 分配temp1到索引值。
于 2012-02-15T17:22:45.237 回答
0

表达式(或子表达式)有两个方面:它的值和它的副作用。的值i ++是 的值i;的值++ i是值i + 1,转换为的类型i。这是表达式中使用的值。两者的副作用是增加变量i。这可能发生在前一个序列点之后和下一个序列点之前的任何时间。假设i是一个全局变量,并且您编写如下内容:

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

该标准没有说明i看到f() 或的值g()是在增量之前还是之后。在这两种情况下都没有。所有标准都说增量的效果将在完整表达式开始之后(但可能作为完整表达式中的第一件事)和结束之前发生。(并且它们不会与函数调用交错,因此如果f() 读取i两次,则可以保证看到相同的值。)

于 2012-02-15T17:37:45.413 回答
0

不幸的是,在您发布的那两个代码片段中,没有保证评估顺序。如果你的表达不恰当,或多或少都会发生任何事情。

先从 a++ 和 ++a 的区别说起:

  • a++ 将递增 a 但使用它的表达式将在递增之前看到 a 的值
  • ++a 将增加 a,并且使用它的表达式将看到增加的值。
  • 项目清单

buffer[a++] = b;

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

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

或这个

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

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

于 2012-02-15T17:58:44.090 回答