• 参数传递方式


    参数传递方式教材上大都说有两种,一种是值传递,另一种是指针传递。而后者本质上依然是值传递。

    底层原理

    对于值传递还是指针传递,传递的都是相应的值,只不过指针传递传递的是地址的副本,修改副本对原来数据没有任何影响,需要修改的是地址的指向。关于函数调用的执行流程可参考strcpy为何不安全

    bool test(int* x) {
        int b = 10;
        //memcpy(a, &b, sizeof(int));
        x = &b;
        //*a = b;
        return true;
    }
    
    int main()
    {
       // std::cout << "Hello World!\n";
        std::string filename = "11.png";
       // FILE* fp = fopen(filename.c_str(), "rb");
        char* s = new char[20];
        int a = 0;
        int * p = &a;
        test(p);
        std::cout << a;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    此时的运行结果是0
    而将代码修改为

    bool test(int* x) {
        int b = 10;
        //memcpy(a, &b, sizeof(int));
        //x = &b;
        *x = b;
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    此时的运行结果是10,也就是修改后的内容。
    两段代码的区别:第一段代码 x = &b;对应的汇编代码是,修改的是x的值得,对原本的数据a没有任何影响。

    00B62F26  lea         eax,[b]    //将b所指向的内存地址(而不是b的值)加载到eax寄存器中
    00B62F29  mov         dword ptr [x],eax  //将 eax 寄存器中的32位(双字)值存储到 x 所指向的内存地址中
    
    • 1
    • 2

    而*x = b;对应的汇编代码是,修改可地址的指向。

    00492F1C  mov         eax,dword ptr [x]   //将x的值赋值给eax,x的值是a对应的地址
    00492F1F  mov         ecx,dword ptr [b]  //将b内存中的值复制给ecx
    00492F22  mov         dword ptr [eax],ecx  //将ecx的值赋值给eax指向的内存中的值
    
    • 1
    • 2
    • 3

    char *传值问题

    bool test(int* x, char * str) {
        char* p = new char[200];
        memset(p, 0, 200);
        p[0] = 'H';
        p[1] = 'E';
        p[2]  = 'l';
        p[3] = '\0';
        int len = strlen(p);
        strcpy_s(str, strlen(p)+1, p);
        delete(p);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    不能使用str = p;这种只是修改副本的值,对原来的char*没有任何影响。

    list传值问题

    c++中list传递需要使用指针或者引用,才能改变原本的值。

    bool test_list(list<string> *testList) {
        testList->push_back("3");
        return false;
    }
    
    • 1
    • 2
    • 3
    • 4

    调用方:

    List<String> li;
    li.push_back("1");
    li.push_back("2");
    test_list(&li);
    
    • 1
    • 2
    • 3
    • 4

    或者

    list<string> *li =  new std::list<string>();
    li->push_back("1");
    li->push_back("2");
    test_list(li);
    
    • 1
    • 2
    • 3
    • 4

    这两个语句都是用于创建一个存储字符串的列表。主要的区别在于:

    1. 数据类型的差异:前者使用的是C++标准库中的list容器,后者是使用指针创建的动态内存。

    2. 声明方式的差异:前者是一般的对象声明方式,后者是通过new运算符动态地分配内存并返回一个指向该内存区域的指针。

    3. 内存管理的差异:前者是一个自动管理内存的对象,当程序执行到其作用域结束或者该对象被销毁时,内存会自动释放;后者需要手动使用delete运算符释放动态分配的内存。

    因此,建议在使用时考虑到实际情况,选择合适的声明方式和内存管理方式。如果只是需要临时存储字符串,并且不想手动管理内存,可以选择前者;如果需要在程序运行期间动态地分配和释放内存,并且需要手动管理内存,可以选择后者。

    c#中的list传递,不需要指针或者引用。像java之类的语言类似,这也是java等语言比c相对简单的原因。

    List<String> li = new List<String>();
    li.Add("1");
    li.Add("2");
    await test(li);
    Console.WriteLine(li);
    Task test(List<String> list_test)
    {
        list_test.Add("3");
        return Task.CompletedTask;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    uni-app —— 小程序登录功能的相关实现
    谈谈selenium4.0中的相对定位
    R语言dplyr包arrange函数排序dataframe数据、通过多个数据列排序dataframe数据(默认是升序排序)
    【树莓派】了解wiringPi库、控制继电器
    Flink sql 实现 -connection-clickhouse的 source和 sink
    C++深浅拷贝及简易string类实现
    qmake eval(string) 函数
    C语言--冒泡排序和简答选择排序
    目标检测笔记(十五): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
    软件测试功能测试全套常见面试题【功能测试】面试总结4-2
  • 原文地址:https://blog.csdn.net/helloworlddm/article/details/134459702