以下程序各有何问题?

***********************************************************************************************************************************

1.

void getmemory(char*p)

{
p=(char *) malloc(100);

}

int main()

{

char *str=NULL;
getmemory(str);

strcpy(str,“helloworld”);

printf("%s\n",str);

}

首先先回顾值传递与指针传递,引用传递的区别:

#include <iostream.h>
void swap(int x,int y)
{
    int temp;
    temp=x;
    x=y;
    y=temp;
}

void swap(int *x,int *y)

{
    int temp;
    temp=*x;
    *x=*y;
    *y=temp;
}

void swap(int& x,int& y)
{
    int temp ;
    temp=x;
    x=y;
    y=temp;
}
void main()
{
    int x=5; int y=6;
    swap(x,y);         

  *****5,6;值传递是在函数作用域中建立变量或对象的副本,一旦函数结束副本消失,不影响原值;

  /*swap(&x,&y);*/

******6,5;指针传递传递的是变量或对象的地址,是在对变量或对象的原值进行操作,会改变原值;

  /*swap(x,y);*/  

*******6,5;引用传递形式如值传递但效果同指针传递,是原来变量或对象的别名,是在对变量或对象的原值进行操作

    cout<<“交换后:x=”<<x;
    cout<<“y=”<<y<<endl;
}

题1就如同是值传递,对原值str不起任何影响,str 依旧是NULL,每运行一次就有一块内存泄露,所以当函数的参数是一个指针,不要指望用该指针去申请动态内存。

*********************************************************************************************************************************

2.

void getmemory(char*p)

{
p=(char *) malloc(100);
strcpy(p,“helloworld”);
}
int  main( )
{
char *str=NULL;
getmemory(str);
printf(“%s/n”,str);
free(str);
return 0;

}

有题1 可知道,str最终没有分配到内存,free(str)是危险操作;

************************************************************************************************************************************

3.

void *getmemory(void)

{
char p[]="hello";

return p;

}

int main()

{

char *str=NULL;
str=getmemory();

printf("%s\n",str);

}

不要用return 语句返回指向“栈内存”的指针,因为该内存在函数结束时自动释放,str指向的地址原先内容不可知,现有内容不清楚,输出乱码

注意:函数的返回值是指针类型的,检查是静态内存指针还是堆内存指针还是栈内存指针,栈内存指针是绝对要不得滴

************************************************************************************************************************************

4.

void  getmemory(char** p,int num)

{
*p=(char*)malloc(num);

}

int main()

{

char *str=NULL;
getmemory(&str,100);

strcpy(str,“helloworld”);

printf("%s\n",str);

}

用指向指针的指针(二级指针)申请动态内存,(c中常用的指针传递)该函数能正常输出helloworld,但是忘记free()会造成内存泄露;

注意:(指针传递,一级指针)函数中只能对指针的指向的值(*p)进行修改,

而不能修改指针地址(改变p值,*p不变)!

例:

void fun(int *p)

{

int b=100;

p=&b;       //  b的地址并没有被返回

}

程序4:

void fun(int *p)

{

*p=100; // okay

}

(函数要求修改指针参数的地址,必须使用指针的指针!(二级指针)

(那么c++中可以运用引用传递来动态申请内存void  getmemory(char*& p,int num)

 

********************************************************************************************************************************

5.

int main()

{

char* str=(char*)malloc(100);

strcpy(str,“hello”);

free(str);

if(str!=NULL)

{

strcpy(str,“world”);

printf(str);

}

return 1;

}

str 所指的内存被释放,但是str 所指的地址仍然不变,if(str!=NULL)没有任何作用。

str变成野指针,“野指针”不是NULL 指针,是指向“垃圾”内存的指针,

“野指针”的成因主要有两种:
(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL 指针,它
的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么
将指针设置为NULL,要么让它指向合法的内存。例如
char *p = NULL;
char *str = (char *) malloc(100);
(2)指针p 被free 或者delete 之后,没有置为NULL,让人误以为p 是个合法的指针。
(3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:
class A
{
public:
void Func(void){ cout << “Func of class A” << endl; }
};
void Test(void)
{
A *p;

{

A a;

p = &a; // 注意 a 的生命期

}

p->Func(); // p 是“野指针”
}
函数 Test 在执行语句p->Func()时,对象a 已经消失,而p 是指向a 的,所以p 就成了“野指针”。

 

*********************************************************************************************************************************

内存管理

中软面试题: 

内存有哪几种存储组织结构.请分别加以说明《来自高质量c/c++编程》

1.从静态存储区域分配:

内存在程序编译时就已经分配,这块内存在程序整个运行过程都存在。(全局变量,static变量)

2.在栈上创建:

函数内部的局部变量在栈上创建,函数结束后,这些存储单元会自动释放。 分配内存效率高,但是分配内存容量有限

3.从堆上分配(动态内存分配):

由malloc()和new()手动分配内存,由delete(),free()手动释放内存空间。内存空间由程序员自己决定,可分配的内存容量大。

注意:

malloc申请的是连续的一块内存,当返回NULL表示内存申请失败,用if(NULL!=p)验证, 若是内存分配失败用exit(1),终止整个程序; 栈出现内存泄露情况通常是由没有回收垃圾资源,没有进行内存释放引起的

 free(p);斩断了指针与这块内存的关系,

          虽然指针P仍然保存原来的地址,但是已经失去了对那块内存的控制权,同样,对应的那块内存虽然内容存在,不过,已经无法利用其中的数据,成为垃圾文件对于每次malloc()只能有一次free(),若free()两次会出错,除非原指针指向NULL

全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的?

生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁;局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;内存中分配在全局数据区。

使用方式不同:通过声明后全局变量程序的各个部分都可以用到;局部变量只能在局部使用;分配在栈区。
操作系统和编译器通过内存分配的位置来知道的,

全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面。

fmoonstar 更新至2011.11.4

c++值传递和引用及指针传递区别的更多相关文章

  1. c++中的引用与指针的区别

    http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...

  2. C++中引用与指针的区别(详细介绍)

    C++中引用与指针的区别(详细介绍) C++中的引用与指针的区别   指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一 ...

  3. [ZZ]C++中,引用和指针的区别

    (1) 引用总是指向一个对象,没有所谓的 null reference .所有当有可能指向一个对象也由可能不指向对象则必须使用 指针. 由于C++ 要求 reference 总是指向一个对象所以 re ...

  4. C++基础之引用与指针的区别与联系、常引用使用时应注意的问题

    什么是引用? 引用就是对变量起一个别名,而变量还是原来的变量,并没有重新定义一个变量.例如下面的例子:   #include<iostream> using namespace std; ...

  5. c++引用与指针的区别

    c++引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址:引用是某块内存的别名. 指针的权威定义: In a declaration T D where ...

  6. <转>c++引用与指针的区别(着重理解)

     ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址:引用是某块内存的别名.  ★ 区别: 1. 指针是一个实体,而引用仅是个别名: 2. 引用使用时无需解引用(*),指 ...

  7. 參数传递(引用,指针,值传递)C++11

    C++中,函数的參数传递方式有值传递.地址传递.传地址有指针和引用方式. 在函数參数中,传地址的理由有: 1.使被调函数能够改动主调函数中的数据对象: 2.传地址能够降低数据拷贝,提高程序运行速度. ...

  8. C、C++中引用与指针的区别

    1:引用的和指针在概念上的区别 引用是变量的别名,例如 int m; int &n=m; 引用作为一个别名.它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用 ...

  9. 引用的作用&引用与指针的区别

    引入 C语言中函数有两种传参的方式: 传值和传址.以传值方式, 在函数调用过程中会生成一份临时变量用形参代替, 最终把实参的值传递给新分配的临时变量即形参. 它的优点是避免了函数调用的一些副作用, 但 ...

随机推荐

  1. nginx添加模块

    [root@VM_0_3_centos nginx]# ./sbin/nginx -V nginx version: nginx/1.12.2 built by gcc 4.8.5 20150623 ...

  2. redis过期策略+事务+分布式锁+单redis服务器锁

    过期策略 相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略.redis 提供 6种数据淘汰策略: voltile-lru:从已设置过期时间的数据集(server.db[i ...

  3. word-wrap与word-break为长单词换行

    如果你遇到长串英文单词或者url换行的问题,这时候就需要用到word-wrap与word-break这2个css属性啦. word-wrap:break-word;长单词与url地址自动换行. wor ...

  4. PowerShell~文件操作和对象遍历

    ps提供了丰富的文件操作,如建立,删除,改名,移动,复制,文件夹建立,显示文件列表,同时对数组对象的遍历也很方便,如果在使用PS脚本时,希望现时传入参数,可以把参数声明为param,当然需要把它写在文 ...

  5. idea使用Git提交代码时忽略指定文件或文件夹

    简述 使用idea编写代码并使用git作为版本控制器的时候,常常不需要提交配置文件以及一些其他不需要提交的文件,可以使用.ignore插件来在上传的时候忽略一些文件或文件夹. 安装 注意:安装完成之后 ...

  6. js中不容小觑的var声明

    在学习vue相关课程中,有一次跟着老师敲代码,写出了如下代码: var Child = { template:`<div @click='handleClick'><slot> ...

  7. requirejs&&springboot

    1.Spring Boot Spring boot 基础结构主要有三个文件夹: (1)src/main/java  程序开发以及主程序入口 (2)src/main/resources 配置文件 (3) ...

  8. 笔记《精通css》第2章 选择器,注释

    第2章    选择器,注释 1.常用选择器(id选择器,类选择器,类型选择器,后代选择器,伪类选择器(文档结构之外)) 通用选择器(*{    }) 高级选择器(子选择器,相邻同胞选择器,属性选择器) ...

  9. Apache的HttpClient的使用

    Apache的HttpClient可以被用于从客户端发送HTTP请求到服务器端,其中封装了客户端发送http的get和post请求 使用Apache的HttpClient发送GET和POST请求的步骤 ...

  10. Traceroute侦测主机到目的主机之间所经路由情况的重要工具

    ICMP的应用--Traceroute Traceroute是用来侦测主机到目的主机之间所经路由情况的重要工具,也是最便利的工具.前面说到,尽管ping工具也可以进行侦测,但是,因为ip头的限制,pi ...