c++函数参数和java的函数参数对比讲解

1.对于c语言

函数参数有两种可能,第一种是拷贝赋值,第二种是指针赋值
代码

#include <cstdio>

using namespace std;

void test_value(int a){
    a = 5;
    printf("test_value a address = %p\n", &a);
}
void test_pointer(int* a){
    *a = 10;
    printf("test_pointer a address = %p\n", a);
}

int main()
{
    int a = 1;
    int b = 1;
    printf("pre main a = %d\n", a);
    test_value(a);
    printf("main a address = %p\n", &a);
    printf("now main a = %d\n", a);

    printf("//////////////////\n");

    printf("pre main b = %d\n", b);
    test_pointer(&b);
    printf("main b address = %p\n", &b);
    printf("now main b = %d\n", b);

    /*pre main a = 1        //最开始a的值
    test_value a address = 0061fe80  a的地址
    main a address = 0061fe9c   调用函数,函数参数的值的地址,
    可以看出不是一个地址,所以对函数参数更改不会更改到本来的a
    now main a = 1         //a没有发生变化
    //////////////////
    pre main b = 1         //最开始b的值
    test_pointer a address = 0061fe98   //函数参数指针的值
    main b address = 0061fe98  //b的地址值,和指针的值相同
    now main b = 10        //所以对指针代表的地址的值的更改会同步到b中,因为是一个
    */
    return 0;
}

使用指针赋值可以通过获得变量的地址进而改变变量本身的值,缺点野指针,使用智能指针解决
使用变量拷贝可以传递参数进行使用,缺点拷贝会带来内存消耗

对于c++

c++相对于c来说增加了引用这一特性,引用的诞生就是为了减少指针的使用,使用引用也就是使用变量本身
int a = 10;
int& a1 = a;
int* a2 = &a;
严格来说a1和a2现在都代表变量a,代表a这个值的方法是a1和*a2,c++把&进行特殊对待,本质也是指针
代码(由于c++有函数重载,这里函数名使用相同的)

#include <iostream>

using namespace std;

void test_value(int a){
    a = 5;
    std::cout << "test_value address = "<< &a << std::endl;
}
void test(int* a){
    *a = 10;
    std::cout << "test_pointer address = "<< a << std::endl;
}
void test(int& a){
    a = 20;
    std::cout << "test_quote address = "<< &a << std::endl;
}

int main()
{
    //由于值传递和引用传递都可以被调用,会有二义性,这里对于value_copy使用不同函数
    int a = 1;
    std::cout << "pre main a value = "<< a << std::endl;
    std::cout << "pre main a pointer = "<< &a << std::endl;
    test_value(a);
    std::cout << "now main a value = "<< a << std::endl;
    std::cout << "//////////////////"<< std::endl;

    a = 1;
    std::cout << "pre main a value = "<< a << std::endl;
    std::cout << "pre main a pointer = "<< &a << std::endl;
    test(a);
    std::cout << "now main a value = "<< a << std::endl;
    std::cout << "//////////////////"<< std::endl;

    a = 1;
    std::cout << "pre main a value = "<< a << std::endl;
    std::cout << "pre main a pointer = "<< &a << std::endl;
    test(&a);
    std::cout << "now main a value = "<< a << std::endl;

    /*
    pre main a value = 1
    pre main a pointer = 0x61fe8c
    test_value address = 0x61fe70
    now main a value = 1
    //////////////////
    pre main a value = 1
    pre main a pointer = 0x61fe8c
    test_quote address = 0x61fe8c
    now main a value = 20
    //////////////////
    pre main a value = 1
    pre main a pointer = 0x61fe8c
    test_pointer address = 0x61fe8c
    now main a value = 10
    */
    return 0;
}

第一次由于是值传递,地址不一样,值相同进行了拷贝,所以对函数参数更改不会影到原来的变量
第二次由于是引用传递,引用传递时代表传入变量本身,可以看出对引用取地址的值和对原来变量取地址得到的值是相同的,所以值发生了更改
第三次指针传递,和c语言一样,指针的值和传入变量的地址相同,所以指针可以修改原来变量的值,原来变量发生了改变
!!c++引用代表的是初始化赋值的变量本身而不是变量代表的地址,引用跟随变量走,举个例子

#include <iostream>

using namespace std;
int main()
{
    int a = 1;
    int& a1 = a;

    std::cout << "a = " << a << std::endl;
    std::cout << "a1 = " << a << std::endl;

    a = 10;

    std::cout << "a = " << a << std::endl;
    std::cout << "a1 = " << a << std::endl;

    int* b = new int(10);
    int& b1 = *b;

    std::cout << "b = " << a << std::endl;
    std::cout << "b1 = " << a << std::endl;

    *b = 10;

    std::cout << "b = " << a << std::endl;
    std::cout << "b1 = " << a << std::endl;
    return 0;
}
输出
a = 1
a1 = 1
a = 10
a1 = 10

b = 10
b1 = 10
b = 10
b1 = 10

可以看出引用跟随的是第一个赋值给引用的那个变量,本质是指针指向

对于java

首先明确java里面不存在指针,存在的变量都是"特殊"引用,为什么特殊,因为引用在c++中必须初始化赋值,java不需要,java引用可以随时赋值
因为java里面有了内存回收机制:
String a = new String("main");//首先分配了一个内存,然后使用a指向这个内存
这里多说一下,java是分基本类型和非基本类型的,不允许像c++ int a = new int(1);这样
对于java函数参数同样使用

class Test {
  private int m_age;
  public Test(int age) {
      m_age = age;
  }
  public void setAge(int age) {
      m_age = age;
  }
    public int getAge() {
        return m_age;
    }


};
public class RedDuck {
    public static void test(String test) {
        test = "test";
    }
    public static void test1(int test) {
        test = 20;
    }
    public static void test1(Integer test) {
        test = 30;
    }
    public static void testAge(Test testage) {
        testage.setAge(30);
    }
    public static void main(String[] args) {
        //两种情况
        //对于基本类型
        int a = 10;  //基本类型本身代表的就是数值
        test1(a);    //形参改变不会影响实参
        System.out.println(a); //输出10

        Integer a_integer = 20; //虽然是包对象,但是仍然和基本类型一样
        test1(a_integer);
        System.out.println(a_integer);

        String string_a = new String("main"); //String 比较特殊,每次的赋值都是重新在内存池新造一个字符串存储在字符串的内存池
        test(string_a);                      //更改形参的指向原来的值不会发生改变
        System.out.println(string_a);
        
        //a的值没有改变为什么呢,因为java这里仅仅是改变的test的指向,并没有改变原来的a,java引用代表的是内存(而不是变量本身),可以随时更改
        //那么什么时候会改变?,就是不整体改变形参的指向改变形参指向的值内部的值

        Test test = new Test(10);
        System.out.println(test.getAge()); //输出 10
        testAge(test);
        System.out.println(test.getAge()); //输出 30

    }
}

我觉得就是你要清楚你指向的是什么东西,java中是针对内存传参的,c++的引用是针对变量本身

posted @ 2020-05-06 21:54  make_wheels  阅读(334)  评论(0编辑  收藏  举报