关于函数返回值的几种情况

引用:http://patmusing.blog.163.com/blog/static/13583496020113191407531/

在一个函数的内部,return的时候返回的都是一个拷贝,不管是变量、对象还是指针都是返回拷贝,但是这个拷贝是浅拷贝。

 

1.     如果返回一个基本类型的变量,比如:

int a;

a = 5;

return a;

 

那么就会a的一个拷贝,即5返回,然后a就被销毁了。尽管a被销毁了,但它的副本5还是成功地返回了,所以这样做没有问题。

 

2.     但是对于非动态分配(new/malloc)得到的指针,像1那么做就会有问题,比如在某个函数内部:

int a[] = {1, 2};

return a;

那么也会返回指针a的一个拷贝,我们假定a的地址值为0x002345FC,那么这个0x2345FC是能够成功返回的。当return执行完成后,a就要被销毁,也就是0x002345FC所指向的内存被回收了。如果这时候在函数外面,去地址0x002345FC取值,那得到的结果肯定是不对的。这就是为什么不能返回局部指针的原因。返回局部变量的引用的道理和这个类似。

 

3.     对于返回(动态分配得到的)指针的另外一种情况,比如在函数内部:

int a = new int(5);

return a;

这样做是可以的。return a执行完后,a并没有被销毁(必须要用delete才能销毁a),所以这里返回的a是有效的。

 

4.     如果不是基本数据类型,比如:

class A

{

public:

               OtherClass * ...

};

 

如果在某个函数内部有一个A类的局部变量,比如:

A a;

return a;

这时候也会返回a的一个拷贝,如果A没有写深拷贝构造函数,就会调用缺省的拷贝构造函数(浅拷贝),这样做就会失败的;

如果A中提供了深拷贝构造函数,则这样做就是可以的。

 

实验代码如下:

#include <iostream>

using namespace std;

int some_fun1()

{

    int a = 5;

    return a;                   //OK

}

 

int* some_fun2()

{

    int a = 5;

    int *b = &a;

    return b;                   // not OK

}

 

int* some_fun3()

{

    int *c = new int(5);

    return c;                   // OK, return c执行完后并没被销毁必须要用delete才能销毁

}

 

class CSomething

{

public:

    int a;

    int b;

 

public:

    CSomething(int a, int b)

    {

        this->a = a; 

        this->b = b;

    }

};

 

class CA

{

private:

    CSomething* sth;            // 以指针形式存在的成员变量

                               

public:

    CA(CSomething* sth)

    {

        this->sth = new CSomething(sth->a, sth->b);

    }

 

    // 如果不实现深拷贝,请注释这个拷贝构造函数

    CA(CA& obj)

    {

         sth = new CSomething((obj.sth)->a, (obj.sth)->b);

    }

 

    ~CA()

    {

        cout << "In the destructor of class CA..." << endl;

        if (NULL != sth) delete sth;

    }

    void Show()

    {

        cout << "(" << sth->a << ", " << sth->b << ")" << endl;

    }

    void setValue(int a, int b)

    {

        sth->a = a;

        sth->b = b;

    }

    void getSthAddress()

    {

        cout << sth << endl;

    }

};

 

CA some_fun4()

{

    CSomething c(1, 2);

    CA a(&c);

    return a;                       // 如果CA没有实现深拷贝not OK如果实现深拷贝OK

}

 

int main(int argc, char* argv[])

{

    int a = some_fun1();

    cout << a << endl;              // OK

 

    int *b = some_fun2();

    cout << *b << endl;             // not OK即便返回结果正确也不过是运气好而已

 

    int *c = some_fun3();           // OK, return c执行完后c并没有被销毁必须要用delete才能销毁

    cout << *c << endl;

    delete c;

 

    CA d = some_fun4();             // 如果CA没有实现深拷贝not OK如果实现深拷贝OK

    d.Show();

 

 

    return 0;

}

 


<think>好的,我现在要回答用户关于C语言函数返回值形式的问题。首先,我需要回顾用户提供的引用内容,确保回答准确。用户提到了几个引用,主要涉及函数返回值的类型、return语句的使用以及相关注意事项。 首先,根据引用[1],函数返回值通过return语句获得,如果函数没有返回值,类型为void,且不能使用return语句。如果有返回值,则必须使用return,并且类型要一致。例如,char类型的函数返回'A',int返回0。 接下来,引用[2]提到,如果函数没有数据返回,返回值类型设为void。如果返回值类型与函数定义不一致,以定义类型为准,系统会隐式转换。这点很重要,比如如果函数声明为int,但return返回的是float,系统会自动转换。 然后,引用[3]指出,return后面可以直接跟分号,适用于void类型。同时,return后的代码不再执行,分支语句必须每个路径都有return,否则编译错误。比如在if-else中,每个条件都要有返回。 引用[4]说明,没有返回值函数可以用void,且可以省略return。如果未明确返回值类型,默认是int。函数不能嵌套定义,定义顺序影响调用,需要声明。 引用[5]的例子显示,void函数没有返回值,但可以有参数,如buyRice函数。 现在,我需要组织这些信息,分点说明返回值的形式和类型。首先,基本语法结构,然后具体类型,包括void、基本类型、指针等。接着是return的用法,注意事项如类型转换、函数终止、分支覆盖等。同时,要举例子,比如int返回0,void函数无返回,指针返回地址等。 还要注意用户可能混淆的地方,比如默认返回值类型是int,这在C89中常见,但C99可能不支持,需要提及。此外,函数声明的位置影响调用,如果函数定义在main之后,需要提前声明。 最后,生成相关问题,如返回值类型不匹配如何处理,void函数能否用return,多return语句的影响,如何返回多个值等。确保问题覆盖常见疑惑点,帮助用户深入理解。</think>### C语言函数返回值形式与类型详解 C语言函数返回值通过`return`语句实现,其形式与类型由**函数定义时的返回值类型**决定,具体可分为以下四类: --- #### 一、基本返回值形式 1. **明确返回值类型** ```c int sum(int a, int b) { return a + b; //返回int类型 } ``` - 返回值类型需与函数定义一致(如`int`、`float`等)[^1]。 - 若返回值类型与函数声明不一致,系统会隐式转换(如`return 3.14;`在`int`类型函数中返回`3`)[^3]。 2. **无返回值(void类型)** ```c void printMsg() { printf("Hello"); return; //可省略 } ``` - `void`表示无返回值函数体内可省略`return`[^4]。 --- #### 二、特殊返回值形式 1. **默认返回类型(仅C89标准支持)** ```c add(int a, int b) { return a + b; //默认返回int类型 } ``` - 未明确声明返回值类型时,默认`int`(不推荐使用)[^4]。 2. **指针类型返回值** ```c int* createArray(int size) { int* arr = (int*)malloc(size * sizeof(int)); return arr; //返回动态数组地址 } ``` - 可返回指针(如数组、结构体指针)。 --- #### 三、`return`语句规则 1. **函数终止**:`return`执行后,函数立即结束,后续代码不执行[^3]。 ```c int check(int x) { if (x > 0) return 1; printf("x非正"); //若x>0,此句不执行 return 0; } ``` 2. **分支覆盖**:含条件分支时,必须保证所有路径都有返回值[^3]。 ```c int abs(int x) { if (x >= 0) return x; else return -x; //必须覆盖所有情况 } ``` --- #### 四、注意事项 1. **形参与实参分离**:函数内修改形参不影响外部实参[^4]。 2. **函数声明**:若函数定义在调用后,需提前声明(如`int max(int a, int b);`)[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值