You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组按值传递与按引用传递是否相同?代码表现存疑咨询

数组传参:为什么你的代码看起来像按引用传递?

嘿,这个问题其实是C/C++里一个非常经典的“坑”——很多刚接触数组传参的开发者都会踩进去,误以为数组是按值传递,但实际规则完全不是你想的那样。我来给你拆解清楚:

首先直接点破核心:在C和C++中,当你把数组作为函数参数传递时,它并不会按值传递,而是会被自动转换成指向数组第一个元素的指针。这就是为什么你在display函数里打印的&b[i]和main里的&num[i]完全一致——因为b本质上就是指向num数组首元素的指针,操作b[i]其实就是直接操作原数组的元素。

你的代码到底发生了什么?

看一下你的display函数声明:

void display(int b[5], int size)

在C++编译器的眼里,这个声明和下面的写法是完全等价的:

void display(int* b, int size)

编译器会自动把数组类型的参数调整为指针类型。所以当你调用display(num,5)时,传递的并不是整个数组的副本,而是num数组首元素的地址(也就是&num[0])。这就导致display函数里的b[i]和main里的num[i]指向同一块内存区域,地址自然一模一样。

那怎么实现真正的“按值传递”数组?

如果想要传递数组的副本(也就是修改函数内的数组不会影响原数组),有几种靠谱的方法:

方法1:用std::array(C++11及以上推荐)

std::array是C++标准库提供的容器,它可以像普通变量一样按值传递:

#include <iostream>
#include <array>

void display(std::array<int, 5> b, int size) {
    std::cout << "\nIn display function:\n";
    for (int i = 0; i < size; i++) {
        std::cout << b[i] << " at: " << &b[i] << "\n";
    }
    // 修改b的元素,不会影响原数组
    b[0] = 99;
}

int main() {
    std::array<int, 5> num = {2, 4, 6, 8, 10};
    std::cout << "In main function:\n";
    for (int i = 0; i < 5; i++) {
        std::cout << num[i] << " at: " << &num[i] << "\n";
    }
    display(num, 5);
    // 打印原数组,第一个元素还是2
    std::cout << "\nAfter display call, num[0] is: " << num[0] << "\n";
    return 0;
}

运行这段代码你会发现,display里的b元素地址和main里的num完全不同,修改b也不会影响原数组,这才是真正的按值传递。

方法2:把数组包装在结构体里(兼容C和旧版C++)

如果是在C环境或者不能用C++11的场景,可以把数组放进结构体里——结构体是支持按值传递的:

#include <stdio.h>

struct ArrayWrapper {
    int arr[5];
};

void display(struct ArrayWrapper b, int size) {
    printf("\nIn display function:\n");
    for (int i = 0; i < size; i++) {
        printf("%d at: %p\n", b.arr[i], &b.arr[i]);
    }
    b.arr[0] = 99;
}

int main() {
    struct ArrayWrapper num;
    num.arr[0] = 2;
    num.arr[1] = 4;
    num.arr[2] = 6;
    num.arr[3] = 8;
    num.arr[4] = 10;
    
    printf("In main function:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d at: %p\n", num.arr[i], &num.arr[i]);
    }
    display(num, 5);
    printf("\nAfter display call, num.arr[0] is: %d\n", num.arr[0]);
    return 0;
}

传递结构体时会生成整个结构体的副本,里面的数组自然也是独立的副本,同样能实现按值传递的效果。

方法3:传递数组的引用(注意:这是按引用传递,不是值传递)

如果你想让函数直接操作原数组,但又想明确是引用传递(避免指针的歧义),可以用数组的引用作为参数:

void display(int (&b)[5], int size) {
    printf("\nIn display function:\n");
    for (int i = 0; i < size; i++) {
        printf("%d at: %p\n", b[i], &b[i]);
    }
    // 修改b的元素会直接影响原数组
    b[0] = 99;
}

此时b是原数组的引用,地址还是和原数组一致,但写法上更明确是引用类型,避免了指针隐式转换的迷惑性。

你的代码里的其他小问题

顺便提两个容易忽略的细节:

  • using namespace std;在你的代码里没必要,因为你用的是C风格的printf和scanf,没用到std命名空间的内容;
  • void main()不是C++的标准写法,标准应该用int main()并返回0;
  • scanf("%d", pause);这里必须传&pause,不然会导致未定义行为(scanf需要变量的地址来存储输入值)。

内容的提问来源于stack exchange,提问作者Kamal Ahmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:08:53