`
izuoyan
  • 浏览: 8916259 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

关于指针和内存的几个问题

阅读更多

一、"delete p" 会删去 "p" 指针,还是它指到的资料,"*p" ?

该指针指到的资料。"delete" 真正的意思是:「删去指针指到的东西」(delete the thing pointed to by)。同样的英文误用也发生在 C 语言的「释放」指标所指向的记忆体("free(p)"真正的意思是:"free_the_stuff_pointed_to_by(p)" )。

二、能 "free()" 掉由 "new" 配置到的、"delete" 掉由 "malloc()" 配置到的记忆体吗?

不行。在同一个程式里,使用 malloc/free 及 new/delete 是完全合法、合理、安全的;但 free 掉由 new 配置到的,或 delete 掉由 malloc 配置到的指标则是不合法、不合理的。

三、为什麽该用 "new" 而不是 malloc() ?

建构子/解构子、型别安全性、可被覆盖(overridability)。建构子/解构子:和 "malloc(sizeof(Fred))" 不同,"new Fred()" 还会去呼叫Fred 的建构子。同理,"delete p" 会去呼叫 "*p" 的解构子。
型别安全性:malloc() 会传回一个不具型别安全的 "void*",而 "new Fred()" 则会传回正确型态的指标(一个 "Fred*")。
可被覆盖:"new" 是个可被物件类别覆盖的运算子,而 "malloc" 不是以「各个类别」作为覆盖的基准。

四、为什麽 C++ 不替 "new" 及 "delete" 搭配个 "realloc()" ?

避免你产生意外。当 realloc() 要拷贝配置区时,它做的是「逐位元 bitwise」的拷贝,这会弄坏大
部份的 C++ 物件。不过 C++ 的物件应该可以自我拷贝才对:用它们自己的拷贝建构子或设定运算子。

五、该怎样配置/释放阵列?

用 new[] 和 delete[] :

Fred* p = new Fred[100];
//...
delete [] p;

每当你在 "new" 运算式中用了 "[...]" 的话,你就 *!*必须*!* 在 "delete" 陈述中使用 "[]" 。这语法是必要的,因为「指向单一元素的指标」与「指向一个阵列的指标」在语法上并无法区分开来。

六、万一我忘了将 "[]" 用在 "delete" 由 "new Fred[n]" 配置到的阵列,会发生什麽事?

灾难。这是程式者的--而不是编译器的--责任,去确保 new[] 与 delete[] 的正确配对。若你弄错了,编译器不会产生任何编译期或执行期的错误讯息。堆积(heap)被破坏是最可能的结局,或是更糟的,你的程式会当掉。

七、成员函数做 "delete this" 的动作是合法的(并且是好的)吗?

只要你小心的话就没事。所谓的「小心」是:
1) 你得 100% 确定 "this" 是由 "new" 配置来的(而非 "new[]",亦非自订的 "new" 版本,一定要是最原始的 "new")。
2) 你得 100% 确定该成员函数是此物件最後一个会去呼叫的。
3) 做完自杀的动作 ("delete this;") 後,你不能再去碰 "this" 的物件了,包括资料及运作行为在内。
4) 做完自杀的动作 ("delete this;") 後,你不能再去碰 "this" 指标了。换句话说,你不能查看它、将它与其他指标或是 NULL 相比较、印出其值、对它转型、对它做任何事情。

很自然的,这项警告也适用於:当 "this" 是个指向基底类别的指标,而解构子不是virtual 的场合。

八、该怎麽用 new 来配置多维阵列?

有很多方法,端视你对阵列大小的伸缩性之要求而定。极端一点的情形,如果你在编译期就知道所有阵列的维度,你可以静态地配置(就像 C 一样):

class Fred { /*...*/ };

void manipulateArray()
{
Fred matrix[10][20];

//使用 matrix[i][j]...

//不须特地去释放该阵列
}

另一个极端情况,如果你希望该矩阵的每个小块都能不一样大,你可以在自由记忆体里配置之:

void manipulateArray(unsigned nrows, unsigned ncols[])
//'nrows' 是该阵列之列数。
//所以合法的列数为 (0, nrows-1) 开区间。
//'ncols[r]' 则是 'r' 列的行数 ('r' 值域为 [0..nrows-1])。
{
Fred** matrix = new Fred*[nrows];
for (unsigned r = 0; r < nrows; ++r)
matrix[r] = new Fred[ ncols[r] ];

//使用 matrix[i][j]...

//释放就是配置的作:
for (r = nrows; r > 0; --r)
delete [] matrix[r-1];
delete [] matrix;
}

九、怎样确保某类别的物件都是用 "new" 建立的,而非区域或整体/静态变数?

确定该类别的建构子都是 "private:" 的,并定义个 "friend" 或 "static" 函数,来传回一个指向由 "new" 建造出来的物件(把建构子设成 "protected:",如果你想要有衍生类别的话)。

class Fred { //只允许 Fred 动态配置出来
public:
static Fred* create() { return new Fred(); }
static Fred* create(int i) { return new Fred(i); }
static Fred* create(const Fred& fred) { return new Fred(fred); }
private:
Fred();
Fred(int i);
Fred(const Fred& fred);
virtual ~Fred();
};

main()
{
Fred* p = Fred::create(5);
...
delete p;
}

分享到:
评论

相关推荐

    浅析C语言中内存与指针使用的几个问题.pdf

    浅析C语言中内存与指针使用的几个问题.pdf

    指针是C语言可以用来直接访问内存地址

    指针在程序中的应用非常广泛,下面将从以下几个方面来说明指针的应用场景: 1. 数组和字符串 2. 函数参数传递 3. 动态内存分配和释放 4. 结构体和链表操作 在C语言中,我们可以使用malloc、calloc和realloc等函数来...

    C指针示例分析(超全面)

    最全面的C指针示例分析,看完这个文档,指针基本被你征服了(截取一小部分): ... 先声明几个指针放着做例子:  例一:  (1)int*ptr;  (2)char*ptr;  (3)int**ptr;  (4)int(*ptr)[3];  (5)int*(*ptr)[4];

    C语言指针-从底层原理到熟练应用(含源码)

    三、指针的几个相关概念 1. const属性 2. void型指针 3. 空指针和野指针 四、指向不同数据类型的指针 1. 数值型指针 2. 字符串指针 3. 指针数组与数组指针 4. 二维数组和指针 5. 结构体指针 6. 函数指针 ...

    教你全面认识c/c++指针

    指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。... 先声明几个指针放着做例子:  例一:  (1)int*ptr;  (2)char*ptr;  (3)int**ptr;  (4)int(*ptr)[3];  (5)int*(*ptr)[4];

    C++指针的透彻分析

    详细讲解了指针的原理及使用,帮你解除关于指针的种种疑惑!

    让你不再害怕指针(指针的详细介绍)

    先声明几个指针放着做例子: 例一: (1)int *ptr; (2)char *ptr; (3)int **ptr; (4)int (*ptr)[3]; (5)int *(*ptr)[4]; 1.指针的类型 从语法的角度看,你只要把指针声明语句里的指针名字去掉,...

    内存管理内存管理内存管理

    它要完成以下三件事:将分配程序标识为已经初始化,找到系统中最后一个有效内存地址,然后建立起指向我们管理的内存的指针。这三个变量都是全局变量: 清单 1. 我们的简单分配程序的全局变量 int has_...

    VB6指针修改数组,多种方法变量赋值速度对比

    相关技术:如果有个共享变量a(100) as long,可以把数组的指针取出来,然后传到类中,再用 指针.value(0)这样读写,速度会慢一倍,还能接受。 不知道有什么办法修改变量的指针 【活跃】大唐 13:22:05 vb还没有...

    Qt内存溢出检测

    一个Qt内存溢出检测小工具,(需要VLD支持)。

    操作系统(内存管理)

    然后,当通过 free() 将该指针传递回来时,我们只需要倒退几个内存字节就可以再次找到这个结构。 在讨论分配内存之前,我们将先讨论释放,因为它更简单。为了释放内存,我们必须要做的惟一一件事情就是,获得我们...

    深入理解C语言指针

    指针是一种数据类型 指针也是一种变量,占有内存...指针变量和它指向的内存块是两个不同的概念 给p赋值p = 0x1111;只会改变指针变量值,不会改变所指的内容;p = p +1;“p++ 给*p赋值*p=’a’;不会改变指针变量的值,

    C/C++面试之算法系列--几个典型的内存拷贝及字符串函数实现

    C/C++面试之算法系列--几个典型的内存拷贝及字符串函数实现 写一个函数,完成内存之间的拷贝。[考虑问题是否全面,是否考虑内存重叠问题] 返回void *支持链式操作,参数类型是void *以支持任意类型的指针,输入...

    C语言程序设计-指针与数组.pptx

    一个数组占用一段连续的内存单元,数组名即为这段连续内存单元的首地址,一个数组元素的地址就是它所占用的几个连续内存单元的首地址。 2 指针与数组 定义一个指向数组元素的指针变量的方法: int a[10]; int *p; p=...

    0x00000000内存不能为read修复工具

    通过上面的几个例子,可以看到,出现故障的原因有好多种,下面列出已经提到和有可能发生的原因,方便查阅。 问题产生原因原因--解决方法 内存条坏了--更换内存条 双内存不兼容--使用同品牌的内存或只用一条...

    游戏画面就弹出内存不能为read修复工具

    假如你是双内存,而且是不同品牌的内存条混插或者买了二手内存时,出现这个问题,这时,你就要检查是不是内存出问题了或者和其它硬件不兼容。 如果都没有,那就从软件方面排除故障了。 先简单说说原理:内存有个存放...

    linux 共享内存浅析

    字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。 shmkey = ftok( "mcut" , 'a' ); // ...

    Windows 2000内存结构

    内存中的每一个字节都可以用一个32位的指针来寻址。这样,最大的存储空间就是232字节或4000兆字节 (4GB) 。这样,在Windows下运行的每一个应用程序都认为能独占可能的4GB大小的空间。 而另一方面,实际上没有几台...

    浅谈c/c++中使用指针需要注意的问题

    一、使用指针的时候需要注意几点: • 分配空间 • 初始化 • 释放 二、常见的错误有几种: 1)内存分配未成功,却使用了它 编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,使用内存...

    C语言指针学习经验总结浅谈

    这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录。文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较费解的东西...还有指针本身所占据的内存区先声明几个指针放着做

Global site tag (gtag.js) - Google Analytics