每次访问数组时C都会复制元素吗?

时间:2017-07-23 10:07:25

标签: c++ c arrays

C不能返回与C ++不同的引用。这是否意味着如果您访问A[i],它会在评估表达式时复制元素吗?

例如,如果A是一个10 int的数组,A[5]+=1;只会增加评估A[5]时构建的临时副本,这与C ++的向量增加不同实际的第六元素本身?

5 个答案:

答案 0 :(得分:12)

C有一个叫做“左右”的概念。这有点像参考。它不是一个类型(不是类型系统的一部分),但某些C表达式是' lvalues',只有这样的表达式可以是赋值的左操作数(包括op-assign)或者增量/减量。

由于C没有运算符重载,因此不需要在类型系统中进行区分,因为从来没有必要将事物声明为rvalues vs lvalues。希望在C ++中添加运算符重载,从而引入引用类型,使重载运算符的rvalue / lvalue区分清晰。

答案 1 :(得分:5)

如果确实如此,那么根本无法修改数组,表达式A[5]+=1;将无法生效!

相反,当您将标量参数传递给函数时,它的行为类似于副本,因为它在返回时不会被修改。但实际上作为指针传递的数组不会被复制(这将是无法承受的代价),并且在返回时可能会有所不同。

答案 2 :(得分:4)

  

A [5] + = 1;只增加评估A [5]时建立的临时副本

没有。 A[5]+=1;将导致A的第6个元素增加1。

这可能是通过将A[5]复制到CPU中的寄存器,递增并重新复制值来实现的。

这是一个程序:

int main(){
    int A[10];
    A[5]+=1;
    return 0;
}

这是gcc为A[5]+=1;

生成的x86-64汇编程序
    mov     eax, DWORD PTR [rbp-28]
    add     eax, 1
    mov     DWORD PTR [rbp-28], eax

DWORD PTR [rbp-28]移动到32位EAX累加器中,向其添加1并将其移回相同位置。

DWORD PTR [rbp-28]通过其相对于堆栈帧(A的(结束)的位置来标识rbp的第6个元素。

关于参考文献的观点是红鲱鱼。 C和C ++都在编译机器代码(可能通过汇编程序)。这些语言的其他功能对A[5]+=1;的解释或编译方式没有影响。

答案 3 :(得分:2)

C始终在使用A[i]的数组中读取时复制元素,也就是说,当表达式A[i]为“rvalue”时。但是,在考虑写入时,C有一个“左值”表达式的概念,它本质上是表达式语法的一个受限子集,允许作为赋值的目标出现:

X    = Y
*X   = Y
X[i] = Y
X.n  = Y

在这些情况下,“表达式”*XX[i]X.n实际上并未评估为值 - 它们具有相同的语法表达式,为方便起见,但不是相同的语义。您可以将这些视为以下内容:

memcpy(&X,    &Y, sizeof(Y));
memcpy(&*X,   &Y, sizeof(Y));
memcpy(&X[i], &Y, sizeof(Y));
memcpy(&X.n,  &Y, sizeof(Y));

或者,或者将C视为具有多个不同的赋值运算符:

_    = _  // direct assignment
*_   = _  // indirect assignment
_[_] = _  // special case of indirect assignment
_._  = _  // special case of indirect assignment

无论哪种方式,A[5] += 1之类的作业都会增加A的第六个元素的值,正如您所期望的那样,您可以这样验证:

int A[1] = { 1 };
A[0] += 5;
printf("%d\n", A[0]);  // 6

答案 4 :(得分:0)

不,我的数组索引只是一个指针,因此只传递一个位置而不是整个数组,并且实际内存位置的值会受到影响。

尝试以下代码:

#include<stdio.h>
void function(int[]);
int main()
{
    int a[] = {0,1,2,3,4,5,6,7,8,9};
    int i;
    for(i = 0; i < 10; i++)
        printf("%d, ",a[i]);    
    function(a);
    printf("\n");
    for(i = 0; i < 10; i++)
        printf("%d, ",a[i]);
    return 0;
}

void function(int b[])
{
    int i;
    for(i = 0; i < 10; i++)
        b[i] *= 10;
}

OUTPUT