You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C++中函数传参:指针与引用的区别及数组传参相关问题

嘿,咱们一个个来拆解你的问题,都是C++里指针和引用的经典坑点,搞懂了能少踩好多雷!

问题1:function(char *something)function(char &something) 的区别

这俩本质是指针和引用的差异,核心区别体现在这几个方面:

  • 本质与绑定规则
    • char *something 是一个独立的指针变量,它存储的是某个char变量的内存地址。你可以随时修改这个指针的指向(比如让它转而指向另一个char),而且它可以被赋值为nullptr,也就是不指向任何有效内存。
    • char &something 是某个char变量的别名,它和原变量共享同一块内存空间。一旦绑定到某个变量后,就再也不能切换指向其他变量,而且引用必须初始化——你不能声明一个不绑定任何变量的空引用。
  • 语法使用差异
    • 用指针时,要访问它指向的变量必须用解引用操作符*,比如*something = 'a';;如果要修改指针本身的指向,直接赋值就行:something = &anotherChar;
    • 用引用时,直接操作引用名就等同于操作原变量,比如something = 'a';,不需要额外的解引用步骤。
  • 调用方式不同
    • 调用指针版本的函数,你需要传入一个char的地址,比如function(&myChar);,或者直接传一个char*类型的变量。
    • 调用引用版本的函数,直接传char变量本身即可:function(myChar);,编译器会自动帮你完成引用绑定。
问题2:字符数组传参的指针vs引用,以及同名参数的问题

先纠正一个小误区:你写的someFunction(char &arrayToManipulate) {}其实不是传数组引用的正确写法——这个参数是单个char的引用,而非数组的引用。数组的引用必须指定大小,正确写法是someFunction(char (&arrayToManipulate)[50]) {},这样编译器才会识别这是一个大小为50的char数组的引用。

两种传参方式的区别

  • 指针传参(char *arrayToManipulate
    • 当你把数组名传给指针参数时,数组会自动退化为指向首元素的指针。这意味着函数内部无法直接获取数组的真实大小(用sizeof(arrayToManipulate)得到的是指针本身的大小,不是数组的字节数)。
    • 你可以在函数里修改指针的指向(比如arrayToManipulate += 5;让它指向数组的第6个元素),但这种修改不会影响外部的数组名(因为数组名是常量指针,本身不可修改)。
    • 优点是灵活,能接受任意大小的char数组,甚至是动态分配的char*内存。
  • 数组引用传参(char (&arrayToManipulate)[50]
    • 这种方式不会让数组退化,函数内部可以通过sizeof(arrayToManipulate)直接获取数组的真实大小(也就是50*sizeof(char))。
    • 你不能修改这个引用的“指向”(数组本身是固定大小的,引用绑定后也无法切换),但可以自由修改数组里的元素。
    • 缺点是不够灵活,这个函数只能接受大小为50的char数组,其他大小的数组传进去会直接编译报错。

同名参数的问题

当函数的形参和外部的数组同名时(比如你说的someFunction(char &arrayOfChars) {}),语法上完全没问题,但会存在作用域屏蔽的情况:
函数内部访问arrayOfChars时,会优先使用形参(函数的局部作用域),外部的同名数组会被暂时“隐藏”。举个例子:

char arrayOfChars[50] = "hello";

void someFunction(char (&arrayOfChars)[50]) {
    // 这里的arrayOfChars是外部数组的引用,修改它就是修改原数组
    arrayOfChars[0] = 'H';
    // 如果在这里定义同名局部变量,会进一步屏蔽形参
    // char arrayOfChars = 'x'; 此时访问的是这个局部char变量
}

虽然不会报错,但逻辑上很容易混淆,不小心就会写出不符合预期的代码,所以一般不推荐用同名的形参。

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

火山引擎 最新活动