使用二级指针传出参数

      使用指针传出参数时,要注意指针所指向的内存是在函数内分配的还是在函数外分配的,以及是不是在堆上分配的。定义一个指针,但是并没有分配指针指向对象所需的内存空间;当函数返回后,此函数栈中的内存会被释放掉,不要让指针指向此函数栈中的内存空间;要指向堆上或此函数外的内存空间。

1. 参数传递的原则是:形参传给实参,不能反向传递;

2. 一级指针可以在函数内部修改实参指针指向的内容;

如: 

void f(char *p) 
{ 
    p[2] = a;//由实参指向的函数外部的数组的内容就被改变了。
    …… 
} 

如果我们想改变实参本身呢?也就是说,我们连指针值都要改变,如果使用:

void f(char *p) 
{ 
	p = (char *)malloc(10 * sizeof(char))
	//或C++中:p = new char[10];
 	…… 
} 

就不行了,因为在函数内部不能通过改变形参的值来改变实参

但是,可以通过二级指针来改变指针值。

void f(char **p)
{ 
      *p = new char[10]; 
        *p[2] = a; 
        delete char[];
        …… 
} 

      可以这样说,传入一个N级指针,就可以修改N-1级指针,原因还是C的参数传递是值传递的,直接修改形参根本改变不了实参,但可以改变形参指针指向的内容,而N级指针指向的内容就是一个N-1级指针。

注意指针所指向的内存是在函数内分配的还是在函数外分配的,以及是不是在堆上分配的。

你定义了一个指针,但是并没有分配指针指向对象所需的内存空间;当函数返回后,此函数栈中的内存会被释放掉,不要让指针指向此函数栈中的内存空间,要指向堆上或此函数外的内存空间。

代码范例:

#include <stdio.h>
#include <string.h>
char *f_void(void);
void f_2ptr(char **ret);
void f_1ptr(char *ret);
 
 
int main()
{
    char havec[] = "this is a b c d e f";
    char **ret; // Alloc memory for secondary pointer
    char *tmp;  // Alloc memory for first pointer

    ret = &tmp; // this is imporint, why?
    f_2ptr(ret);
    printf("%s\n",tmp); // Ok
    tmp = f_void();
    printf("%s\n",tmp); // Ok
 
    f_1ptr(havec);
    printf("havec = %s\n",havec);
 
    return 0;
}
 
void f_2ptr(char **ret) // output argument, memory is alloced in the function
{
    static char aa[] = "this is output argument";  // 该处的static指定数组aa[]指向全局变量所在空间
    *ret = aa;
}

void f_1ptr(char *ret) // memory is alloced outside the function
{
    char *tmp;
    if((tmp = index(ret,'c')) ==NULL) // this is just a example
        return ;
    *(tmp+4) = '\0';
}
 
 
char *f_void(void) // return a pointer, memory is alloced in global
{
    return "this is return value";
}

运行结果:

root@startech-945GCM-S2C:~/Cisco-MAPI-Test# ./ok
this is output argument
this is return value
havec = this is a b c d


转自:http://blog.youkuaiyun.com/david_xtd/article/details/7175962


<think>好的,用户想了解C++中函数参数的传和传引用用法。我需要先回顾一下相关的知识,并结合提供的引用内容来组织回答。 首先,根据引用[1]和[4],C++默认是传,无论是基本类型还是用户自定义类型。传引用需要显式使用&符号声明参数。例如,引用[3]中的例子展示了传不会修改原变量,而传引用的话需要将参数声明为int& num才能改变原。 接下来,引用[2]中的模板函数byValue展示了传的情况,无论传入的是变量还是临时都可以处理。而引用[5]中的UE4例子使用了const FString&,说明传常引用的用法,避免拷贝同时防止修改。 用户的问题涉及传入传出参数,可能需要区分输入参数和输出参数。通常传const引用用于大对象输入,而普通引用用于输出参数。例如,void func(const BigClass& input, int& output)这样的形式。 需要指出何时使用、传引用,以及指针作为另一种传引用的方式。比如,指针需要显式解引用,而引用更安全。还要提到右引用和移动语义,但根据现有引用可能不需要深入,除非用户提到。 注意事项部分可以包括避免返回局部变量的引用,传引用可能引起的悬挂引用问题,以及性能考量。例如,对于小型结构体,传可能更高效;大型数据则传引用更好。 最后生成相关问题,可能涉及性能比较、const的作用、指针与引用的区别,以及实际应用场景如STL中的使用。 需要确保回答结构清晰,分点说明,代码示例正确,并正确标注引用来源。例如,在传示例中使用引用[3]的代码,传引用部分添加修改后的代码,并引用[1]和[4]来说明默认行为。</think>### C++函数参数传递方式详解 C++函数参数传递主要分为传(by value)和传引用(by reference)两种方式,理解这两种机制需要从内存操作层面分析。 #### 一、传(Pass by Value) 1. **基本特性** - 创建参数的独立副本 - 函数内修改不影响原始变量 - 适用场景:基本类型、小型结构体、不需要修改原始参数 ```cpp void modifyValue(int num) { num = 100; // 仅修改副本 } int main() { int x = 42; modifyValue(x); cout << x; // 输出42 [^3] } ``` 2. **底层原理** - 调用时发生拷贝(copy constructor) - 对用户自定义类型可能产生拷贝开销[^4] #### 二、传引用(Pass by Reference) 1. **基本特性** - 直接操作原始变量 - 函数内修改会影响原始 - 语法:参数类型后加`&` ```cpp void modifyReference(int& num) { num = 100; // 修改原始变量 } int main() { int x = 42; modifyReference(x); cout << x; // 输出100 [^1] } ``` 2. **高用法** - 常量引用:`const T&`避免拷贝同时防止修改 ```cpp void printBigData(const BigData& data) { // 只读访问,无拷贝开销 [^5] } ``` - 输出参数:通过引用返回多个 ```cpp void parseInput(const string& input, int& outVal1, bool& outVal2) { // 通过outVal1/outVal2返回结果 } ``` #### 三、参数选择策略 | 特征 | 传 | 传引用 | |---------------|--------------------------|-----------------------| | 内存开销 | 副本空间 | 仅指针大小(4/8字节) | | 修改可见性 | 不可见 | 可见 | | 推荐使用场景 | 基本类型、小型数据结构 | 大型对象、需要修改参数 | #### 四、特殊注意事项 1. 指针参数的实质仍是传(传递指针的副本) ```cpp void modifyPointer(int* p) { p = new int(100); // 仅修改指针副本 } ``` 2. 返回局部变量的引用会导致未定义行为 3. 引用参数必须绑定到有效内存地址 #### 五、现代C++扩展 1. 右引用(C++11+) ```cpp void handleResource(Data&& tempData) { // 移动语义优化资源转移 } ``` 2. 万能引用(模板编程) ```cpp template<typename T> void universalRef(T&& param) { // 自动推导引用类型 } [^2] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值