2012年8月22学习笔记---程序员面试宝典

来源:互联网 发布:网络直播监督平台 编辑:程序博客网 时间:2024/05/23 01:18

1 空类与多重继承的空类以及虚函数的内存占用:

#include <iostream>using namespace std;class A {};class A1 {};class B : public A {};class C : public virtual B {};class D : public A, public A1 {};int main(){cout << sizeof(A) << endl;cout << sizeof(B) << endl;cout << sizeof(C) << endl;cout << sizeof(D) << endl;return 0;}

     空类所占空间为1,单一继承的空类空间也为1,多重继承的空类空间也为1,但是虚继承涉及到虚表(虚指针),所以大小为4。

深入理解sizeof与strlen的区别

1、sizeof操作符的结果类型是size_t,它在头文件中的typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
2、sizeof运算符,strlen是函数。
3、sizeof可以用类型或函数做参数,strlen只能用char*做参数,且必须以"\0"结尾的。
4、数组做sizeof的参数不退化,传递给strlen就退化为指针。
5、大部分编译程序在编译的时候就把sizeof计算过了,是类型或是变量的长度,这就是sizeof(x)可以用来定义数组维数的原因。
6、strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度,而不是类型占内存的大小。
7、sizeof后如果是类型必须加括号,如果是变量名可以不加括号,这是因为sizeof是操作符而不是函数。
8、当使用了一个结构类型或变量时,sizeof返回实际的大小。当使用一静态的空间数组时,sizeof返回全部数组的尺寸。sizeof不能返回被动态分配的数组或外部的数组的尺寸,sizeof计算栈中分配的大小,不计算静态变量。
9、数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:func(char [8]), func(char []), func(char*)等价。在C++中传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小,如果想在函数内知道数组的大小,需要进入函数后用memcpy将数组复制出来,长度由另一个形参传进去。
10、计算结构变量的大小就必须讨论数据对齐问题。
11、sizeof操作符不能用于函数类型、不完全类型或位字段。不完全类型指具有未知存储大小数据的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。


3 内存分配的三种方式:

(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。

(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

4 内存的动态分配:

例如:

void GetMemory(char *p){ p = (char *)malloc(100);}void Test(void){ char *str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str);}

请问运行Test 函数会有什么样的结果?
答:程序崩溃。因为GetMemory 并不能传递动态内存,Test 函数中的 str 一直都是 NULL。

解析: 当Test函数调用GetMemroy(char* p),将str当参数传递给p,其实就是调用之后,p为str副本,就是将str指向的地址赋值给p,但是str是null,是”不存在的“,暂时没分配的;哈哈其实调用GetMemroy时,系统会为其产生一个过程栈使用,而参数p其实就存在“过程栈”上,也就是说调用时,在栈上分配了一个指针char* p,指针吗,其实就是一个会指向其他内存位置的一块地址,の......,其实发现,调用时,传递的str与p自始至终没有任何联系.......这.....这就从根本上说明,动态分配压根不可行........

图示如下:


strcpy(str, "hello world");将使程序崩溃。因为....str为null的,

char* p;p="hello";
会报错(vs),因为p本身并不指向一个存在的地址。

char *GetMemory(void){ char* p = "hello world"; return p;}void Test(void){ char *str = NULL; str = GetMemory(); printf(str);}

请问运行Test 函数会有什么样的结果?
答:可能是乱码。
    因为GetMemory 返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。

void GetMemory2(char **p, int num){ *p = (char *)malloc(num);}void Test(void){ char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str);}


请问运行Test 函数会有什么样的结果?
答:
(1)能够输出hello
(2)内存泄漏


void Test(void){ char *str = (char *) malloc(100); strcpy(str, “hello”); free(str);if(str != NULL){ strcpy(str, “world”); printf(str);}}


请问运行Test 函数会有什么样的结果?


答:篡改动态内存区的内容,后果难以预料,非常危险。因为free(str);之后,str 成为野指针,


if(str != NULL)语句不起作用。
**********************************************************************************************
void GetMemory2(char **p, int num){ *p = (char *)malloc(sizeof(char) * num);}void Test2(void){ char *str = NULL; GetMemory2(&str, 100); // 注意参数是 &str,而不是str strcpy(str, "hello"); cout<< str << endl; free(str);}

如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”.由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。

char *GetMemory3(int num){ char *p = (char *)malloc(sizeof(char) * num); return p;}void Test3(void){ char *str = NULL; str = GetMemory3(100); strcpy(str, "hello"); cout<< str << endl; free(str);}


这里强调不要用return 语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡。

 char *GetString(void){ char *p = "hello world"; return p; // 编译器将提出警告}void Test4(void){ char *str = NULL; str = GetString(); // str 的内容是垃圾 cout<< str << endl;}

用调试器逐步跟踪Test4,发现执行str = GetString 语句后str 不再是NULL 指针,但是str 的内容不是“hello world”而是垃圾。同样是因为存在于过程栈中,用完就有可能释放啦,即使是指针,这种跨栈访问也是危险的。
 char *GetString2(void){ char *p = "hello world"; return p;}void Test5(void){ char *str = NULL; str = GetString2(); cout<< str << endl;}

函数Test5 运行虽然不会出错,但是函数GetString2 的设计概念却是错误的。因为
GetString2 内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内
恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。

总结起来:

因为这个函数返回的是一个局部变量地址,当调用这个函数后,这个局部变量str就随着过程栈的释放而释放啦,所以返回的结果是不确定的,而且还是不安全的。
下面的代码:
#include <iostream>using namespace std;char strone[14];char* strA(){strcpy(strone,"hello world");return strone;}int main(){    char* str=NULL;cout<<str<<endl;char* p=strA();cout<<p;    return 0;}


原创粉丝点击