规则

任何语言,不管是C/C++/JAVA/C#,函数中传递参数或者返回值,都是按照值传递的,都是复制一份原来的变量里面的值。

参数如果是整型则拷贝的是整型里面的整型值,参数如果是指针则拷贝的是指针里面的内存地址

c语言中

返回值实际上存在一个复制

返回整型的时候,复制的是那个整型。

返回指针的时候,复制的是那个指针,但是指针指向的地址在函数的如果在栈上分配(即不是alloc在堆上分配内存),函数执行完后,那块内存已经无效了。

java语言中

返回值实际上存在一个复制

返回整型的时候,复制的是那个整型。

返回对象的时候,复制的是那个对象地址,但是对象指向的地址在方法堆中,方法执行完后,那块内存仍然有效,除非GC回收该堆上内存

  • java方法中传递参数示例
public class Test {
    public static void main(String args[]) {
        int i = 1;
        // 传递给add方法的参数i是复制那个整型值1
        add(i);
        // 输出1,不是2
        System.out.println(i);
    }
    public static void add(int i) {
        // 修改复本i的值,实际上外层i的值仍未改变
        i++;
    }
}
class A {
    public int i = 1;
}
 
public class Test {
    public static void main(String args[]) {
        A a = new A();
        // 传递给add方法的参数a是复制a的地址的复本
        add(a);
        // 输出1,不是2
        System.out.println(a.i);
    }

    public static void add(A a) {
        // 修改a地址指向new A()在堆中创建出来的内存首地址,实际上外层a地址仍未改变
        a = new A();
        a.i++;
    }
}
  • c语言函数中传递参数示例
#include <stdio.h>
#include <stdlib.h>
typedef struct {
    int i;
} A;
static void add(A a) {
    // 修改a的i属性值不会修改上层a的值,因为方法参数传递的是a的拷贝复本
    a.i = 100;
}
int main(void) {
    A a;
    a.i = 1;
    add(a);
    // 输出仍为1
    printf("%d", a.i);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
 int i;
} A;
static void add(A* a) {
    // 函数传递的是a的内存地址拷贝,修改该内存地址指向的属性有效
    a->i = 100;
}
int main(void) {
    A a;
    a.i = 1;
    add(&a);
    // 输出为100
    printf("%d", a.i);
    return 0;
}
  • java方法中返回参数示例
public class Test {
    public static void main(String args[]) {
        // 将create()里面返回的拷贝的值赋值给i
        int i = create();
        // 输出2
        System.out.println(i);
    }
    public static int create() {
        int i = 2;
        // 返回i值的拷贝,即2
        return i;
    }
}
class A {
    public int i = 0;
}
 
public class Test {
    public static void main(String args[]) {
        A a = create();
        // 输出2
        System.out.println(a.i);
    }

    public static A create() {
        // 在堆中分配内存
        A a  = new A();
        a.i = 2;
        // 返回a对象指向的内存地址拷贝,内存地址是在堆中内存地址,返回出去不会被清除
        return a;
    }
}
  • c语言函数中返回参数示例
#include <stdio.h>
#include <stdlib.h>
static int create() {
    int i = 2;
    // 返回i值的拷贝,即整型数值2
    return i;
}
int main(void) {
    // 将create()里面返回的拷贝的值赋值给i
    int i = create();
    // 输出2
    printf("%d", i);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
    int i;
} A;
static A create() {
    A a;
    a.i = 100;
    // 有问题,此时变量a内存分配在栈上,函数返回时栈上分配的空间会清空,虽然存储空间会缓存一段时间
    return a;
}
int main(void) {
    A a = create();
    printf("%d", a.i);
     return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
    int i;
} A;
static A* create() {
    A* a;
    // 在堆上分配内存
    a = malloc(sizeof(A));
    a->i = 100;
    // 返回堆上分配的内存地址的拷贝,内存地址是在堆中内存地址,返回出去不会被清除,除非调用free函数清除堆上内存
    return a;
}
int main(void) {
    A* a = create();
    printf("%d", a->i);
    return 0;
}

参考: