zoukankan      html  css  js  c++  java
  • 关于一道看了很多次,但每次都被似懂非懂的问题

    #include <iostream> 
    void foo(char *p)
    {
       p = "after foo()";
    }     
    void main()
    {
       char *p = "before foo()";
       foo(p);     
       cout <<p <<endl;   
    }

    看到这个,大家很熟悉吧,估计c++面试题中会出现不少。最后输出是before foo(),为什么foo函数没有把p的内容改变。为什么明明传入了指针但改不了指针指向地址的值呢?

    有一点东西必须说明一下的就是,"before foo()"这个字符串其实代表了一个地址。地址的内容是before foo()这几个字符串。同理"after foo()"也是一个地址。

    当实参p传入foo时,形参p和实参p其实都是指向"before foo()"的地址,但是后来foo里面把形参p指向的地址变为了"after foo()"的地址,就再不关"before foo()"这块内存什么事了,所以其实形参p改变的只是自己指向的地址。不要以为p = "after foo()"是把p指向的地址内的字符串替换为了"after foo()"

    类似的函数如:

    void foo(char *p)
    {
       p = new char[10];
    }

    调用这个函数也不会给实参分配内存,它只是将形参指向一块新分配的内存。

    如果foo是这样的:

    void foo(char *p)
    {
       *p = '1';
    }

    这时候实参p指向的地址的值就真的是实实在在地被修改了。但是实参是指向"before foo()"的话,这时传入foo,会发生写入报错,因为"before foo()"所在的内存受到了写保护。

    如果实参是类似char* p = new char[10]{'f','f',''};这样声明的,传入foo,就不会有什么问题,实参p指向地址的首个字符就会从'f'变为'1'

    如果想将实参p = "before foo()"变为"after foo()",可以将foo改为

    void foo(char **p)
    {
    *p = "after foo()";
    }

    调用的时候传入p指针的地址就可以了。

    foo(&p);

    这时候是将实参p指向的地址改变了,而不是改变p指向地址的内容。

    当然方法很多,就不多说了。这些知识可能很多人都知道,不过如何表达让其他人明白就因人而异了,或者有人觉得我写得容易理解,那就看看吧。大神路过跪求指导,或者直接无视继续前进

  • 相关阅读:
    php面试专题---16、MySQL创建高性能索引考点
    php面试专题---Mysql索引类型、介绍及优点
    php面试专题---Mysql索引原理及SQL优化
    北风设计模式课程---责任链模式 总结
    黑马lavarel教程---2、获取用户输入
    php面试专题---15、MySQL数据库基础考察点
    北风设计模式课程---外观模式、代理模式和中介者模式的区别
    legend3---1、meedu安装
    mysql中utf8和utf8mb4区别
    Struts2基于注解的Action配置
  • 原文地址:https://www.cnblogs.com/riversHahaha/p/5320191.html
Copyright © 2011-2022 走看看