【C++】函数传参

本文探讨了C++中指针参数与数组参数的使用方式及其区别。通过具体实例展示了如何正确地使用指针参数来修改外部变量,并讨论了数组作为参数时的特殊行为及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.指针参数

#include "stdafx.h"
#include <iostream>
using namespace std;
char *  a  = new char[20];
void test(char * pArr)
{
    cout<<&pArr<<endl;
    a = "hello";
    pArr = a;
    cout<<pArr<<endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    char * arr = "12321";
    cout<<arr<<endl;
    cout<<&arr<<endl;
    test(arr);
    cout<<&arr<<endl;
    cout<<arr<<endl;
}

输出为:

由第三行可以看出,在传递指针的时候,函数还是进行了形参到实参的拷贝,所以改变函数传入指针的指向值不会影响原来的值。

如果你需要修改指针的值,那么你需要改下参数为:

void test(char * &pArr)

2. 数组参数

   数组参数,会被降阶,转化为指针,从而无法知道数组的长度,所以一般传字符数组的话,也需要传入数组的长度,另外,也可以使用 & 修改值。

 

C++中,函数传参协议指的是函数调用时参数传递的方式,主要包括以下几种: ### 1. **传值(Pass by Value)** - 传递参数的**副本**,函数内对参数的修改不会影响原始值。 - 适用于**基本数据类型**(如`int`、`float`等)或**不需要修改原始对象**的情况。 - **缺点**:对于大型对象(如类对象),拷贝开销较大。 ```cpp void func(int x) { x = 10; // 修改的是副本,不影响原始值 } int main() { int a = 5; func(a); cout << a; // 输出 5(未被修改) return 0; } ``` ### 2. **传引用(Pass by Reference)** - 传递参数的**引用**(即别名),函数内对参数的修改会影响原始值。 - 适用于**需要修改原始对象**或**避免大型对象拷贝**的情况。 - 使用`&`符号声明引用参数。 ```cpp void func(int &x) { x = 10; // 修改的是原始值 } int main() { int a = 5; func(a); cout << a; // 输出 10(被修改) return 0; } ``` ### 3. **传指针(Pass by Pointer)** - 传递参数的**地址**,函数内通过指针修改原始值。 - 适用于**需要修改原始对象**或**动态分配内存**的情况。 - 使用`*`符号声明指针参数。 ```cpp void func(int *x) { *x = 10; // 修改指针指向的值 } int main() { int a = 5; func(&a); // 传递地址 cout << a; // 输出 10(被修改) return 0; } ``` ### 4. **传常量引用(Pass by Const Reference)** - 传递参数的**常量引用**,避免拷贝开销,同时防止函数内修改原始值。 - 适用于**只读访问大型对象**(如`std::string`、类对象等)。 ```cpp void func(const std::string &str) { // str.append("!"); // 错误!不能修改常量引用 cout << str; // 只读访问 } int main() { std::string s = "Hello"; func(s); // 高效传递,避免拷贝 return 0; } ``` ### 5. **传右值引用(Pass by Rvalue Reference,C++11引入)** - 传递**右值引用**(`&&`),用于实现**移动语义**(避免不必要的拷贝)。 - 适用于**临时对象**或**资源转移**的场景。 ```cpp void func(std::string &&str) { std::string local = std::move(str); // 移动资源 } int main() { func("Hello"); // 传递临时对象(右值) return 0; } ``` ### 6. **默认参数(Default Arguments)** - 允许函数调用时省略某些参数,未提供的参数使用默认值。 - 必须在函数声明中指定默认值。 ```cpp void func(int x, int y = 10) { cout << x + y; } int main() { func(5); // 输出 15(y使用默认值10) func(5, 20); // 输出 25(y显式传入20) return 0; } ``` ### 7. **可变参数(Variadic Arguments)** - 使用`...`和`<cstdarg>`实现可变参数函数(如`printf`)。 - C++11推荐使用**模板参数包**(`template <typename... Args>`)或`std::initializer_list`替代。 ```cpp #include <cstdarg> void func(int count, ...) { va_list args; va_start(args, count); for (int i = 0; i < count; ++i) { int x = va_arg(args, int); cout << x << " "; } va_end(args); } int main() { func(3, 1, 2, 3); // 输出 1 2 3 return 0; } ``` ### 总结 | 传参方式 | 语法 | 适用场景 | 是否影响原始值 | |----------|------|----------|----------------| | 传值 | `T x` | 基本类型、小型对象 | ❌ 不影响 | | 传引用 | `T &x` | 修改原始对象、避免拷贝 | ✅ 影响 | | 传指针 | `T *x` | 动态内存、可选参数 | ✅ 影响(需解引用) | | 常量引用 | `const T &x` | 只读大型对象 | ❌ 不影响 | | 右值引用 | `T &&x` | 移动语义、临时对象 | ✅ 可移动资源 | | 默认参数 | `T x = default` | 可选参数 | ❌ 不影响 | | 可变参数 | `...` 或模板 | 不定数量参数 | - | ### 最佳实践 1. **优先传常量引用**(避免拷贝,防止误修改)。 2. **需要修改参数时用普通引用**(如`int &`)。 3. **动态分配内存时用指针**(如`int *`)。 4. **C++11+优先用右值引用优化性能**(如`std::move`)。 5. **避免可变参数**,优先使用模板或`std::initializer_list`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值