c/c++总结

来源:互联网 发布:手机杂志制作软件 编辑:程序博客网 时间:2024/04/28 11:32

确定栈的增长方向

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include<stdio.h>    
  2. static int stack_dir;    
  3. static void find_stack_direction (void)  {    
  4.     static char   *addr = NULL;   /* address of first 
  5.                                      `dummy', once known */    
  6.     char     dummy;          /* to get stack address */    
  7.   
  8.     if (addr == NULL)    
  9.     {                           /* initial entry */    
  10.         addr = &dummy;    
  11.   
  12.         find_stack_direction ();  /* recurse once */    
  13.     }    
  14.     else                          /* second entry */    
  15.         if (&dummy > addr)    
  16.             stack_dir = 1;            /* stack grew upward */    
  17.         else    
  18.             stack_dir = -1;           /* stack grew downward */    
  19. }    
  20.   
  21. int main(void)    
  22. {    
  23.     find_stack_direction();    
  24.     if(stack_dir==1)    
  25.         puts("stack grew upward");    
  26.     else    
  27.         puts("stack grew downward");    
  28.     return 0;    
  29. }   


c++内存分布 http://www.cnblogs.com/skynet/archive/2011/03/07/1975479.html

C++静态库和动态库:http://www.cnblogs.com/skynet/p/3372855.html

讲的很清楚

C++的类型转换:http://www.cnblogs.com/skynet/archive/2010/09/30/1839731.html

C++对象模型:这个不太懂。


placement new: 初始化空间
malloc分配之后,如何初始化
pi = new (ptr) int; pi = new (ptr) int; //placement new


static 使用与作用(有用:http://blog.csdn.NET/Kendiv/article/details/675941)

不可重入性?((不可重入性的例子可以参见<effective C++ (2nd)>(影印版)第103-105页)

线程安全定义?(有用:http://blog.csdn.Net/hairetz/article/details/4281931)


gdb调试(http://blog.csdn.net/haoel/article/details/2879)

大体学一下


结构体对齐和哪个硬件有关?

当CPU访问正确对齐的数据时,它的运行效率最高

跟内存有关吧。


virtual函数的意义,什么时候用,什么时候不用,

除构造函数之外,任何非static成员函数都可以为虚函数?

c++动态绑定条件:1)只有指定为虚函数的成员函数才能动态绑定;2)必须通过基类类型的引用或指针进行函数调用。

构造函数不能定义为虚函数,它是在对象完全构造之前运行的,在构造函数运行时,对象的动态类型还不完整。

赋值运算符设为虚函数会引起混淆,因为虚函数必须在基类和派生类中具有相同的形参,而每个都是自己的类型。

构造函数和析构函数里调用虚函数都是无用的,默认都是静态绑定。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int *p_scalar = new int(5); //allocates an integer, set to 5. (same syntax as constructors)  
  2. int *p_array = new int[5];  //allocates an array of 5 adjacent integers. (undefined values)  
  3. int *cpp11_array = new int[5] {1, 2, 3, 4, 5};    
  4. //allocates an array of 5 adjacent integers initialized to {1, 2, 3, 4, 5}. (C++11 only)  



#include <string.h> extern char* strstr(const char*str1, const char*str2); 其语义就是成功了返回指针,否则返回NULL,注意str2 == NULL的 情况。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. char* strstr(const char *s1, const char *s2){ // haystack, needle  
  2. /* 
  3.     // gcc 4.8.0 
  4.     const char* p = s1; 
  5.     const size_t len = strlen(s2); 
  6.     for(;(p=strchr(p,*s2)) != 0; p++){ 
  7.         if(strncmp(p,s2,len) == 0) 
  8.             return (char*)p; 
  9.     } 
  10.     return (0); 
  11. */  
  12.     int n;  
  13.     if(*s2){  
  14.         while(*s1){  
  15.             for(n = 0; *(s1+n) == *(s2+n); n++){  
  16.                 if(!*(s2+n+1))  
  17.                     return (char*)s1;  
  18.             }  
  19.             s1++;  
  20.         }  
  21.         return NULL;  
  22.     }  
  23.     else{  
  24.         return (char*)s1;  
  25.     }  
  26. }   // #include<string.h>  


String 的构造函数、析构函数、赋值函数

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class String{  
  2. public:  
  3.     String(const char *str = NULL);           //普通构造函数  
  4.     String(const String &other);              //拷贝构造函数  
  5.     ~String(void);                            //析构函数  
  6.     String & operate =(const String &other);  //赋值函数  
  7. private:  
  8.     char *m_data;                             //用于保存字符串  
  9. };  
  10. String::~String(void){  
  11.     delete [] m_data;  
  12.     m_data = NULL;  
  13. }  
  14. String::String(const char *str){  
  15.     if(NULL==str){  
  16.         m_data = new char[1];  
  17.         *m_data = '\0';  
  18.     }  
  19.     else{  
  20.         int length = strlen(str);  
  21.         m_data = new char[length+1];  
  22.         strcpy(m_data,str);  
  23.     }  
  24. }  
  25. String::String(const String &other){  
  26.     int length = strlen(other.m_data);  
  27.     m_data = new char[length+1];  
  28.     strcpy(m_data,other.m_data);  
  29. }  
  30. String & String::operate =(const String &other){  
  31.     if(this== &other){ //检查自复制  
  32.         return *this;  
  33.     }  
  34.     delete [] m_data; //释放原有的内存资源  
  35.     m_data = new char[strlen(other.m_data);+1];  
  36.     strcpy(m_data,other.m_data);  
  37.     return *this;     //返回本对象的引用  
  38. }  

重看《C++primer》

1:class自动生成的function一般都是逐级调用(包括 default ctor, copy ctor, operator=, dtor, const operator& const, operator&),不存在继承问题。

2: 一般base class的dtor为虚函数,否则当出现动态调用时只调用base class的dtor。

3:c++的class内member variable和member function不可以重名。但Java可以。

4: dtor的属性必须为public。

5:char *p1, *p2; p1 == p2(比较的是地址);strcmp(p1, p2)(比较的是值)。

6:c++中不可以overload的operator: ".", "::", "?:", "sizeof", ".*"。

7:char|0X20:功能,转化为大写。 a:0X61, A:0X41, 0:0X30。

8:不存在exception(const char *p),这个只有在继承类(e.p:bad_alloc, runtime_error, bad_exception)中才会定义这个 - TrendMicro。

9:C语言中内存分为4类:

  data segment(text segment): global/static/initialized value

  BSS segment: uninitialized value

  Stack segment: function run

  Heap segment: malloc/free

10: sizeof是operator,返回unsigned int, so sizeof(int)>>32 = 0。

  sizeof括号内在compile 阶段不被编译,而是被取代,e.p: int a= 8; sizeof(a=6); //a=8

  sizeof(function):返回return value的类型。

11:y/*x要特别注意,防止和后面的*/变成注释了。

12:在constructor中,virtual mechanisim 不会发生作用,因为这个是在派生类构造函数之前执行。

13:全局对象的constructor会在main之前执行。

14:int i = 0; ++i = 2; //i=2. i++ = 2; //wrong.

15:A& operator+(); //前缀。 A operator+(int); //后缀

16:动态数组(from http://coolshell.cn/)

  struct{char p[0],char *p};

  struct line{int length; char contents[0];}

17、(http://ihack.sinaapp.com/category/compiler/)这个帖子相当有用

内存回收的基本方法:
1)Reference Counting(引用计数): 每个对象都设置一个参数,就是引用它的变量,引用少一个就减1,多一个就加1,为0时回收
2)Reachability(可达性):有一组基本的对象或变量是可达的,称为root set,这些变量或对象指向的对象也是可达的,同理,一个可达对象指向的对象是可达的。


复制构造函数与赋值构造函数差别?
答:区别在于:复制构造函数是去完成对未初始化的存储区的初始化,而赋值操作符则是处理一个已经存在的对象。对一个对象赋值,当它一次出现时,它将调用复制构造函数,以后每次出现,都调用赋值操作符。

虚析构函数的作用?
答:这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。

内联函数: 在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。由于在编译时将函数体中的代码替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间开销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。

static_cast,const_cast,dynamic_cast,reinterpret_cast的区别?
答:第一个是强制隐式转换,是比较安全的;第二个是去常量性的;第三个是安全向下转型(safe downcasting)最后一个是低级转换。
原因:用C风格的转换其实是不安全的,编译器无法看到转换的不安全,(http://www.cplusplus.com/doc/tutorial/typecasting/)
针对类指针的问题,C++特别设计了更加细致的转换方法,分别有:
static_cast <new_type> (expression):编译器隐式执行的任何类型转换都可以由static_cast显式完成
dynamic_cast <new_type> (expression):将base->derived(引用或指针),涉及运行时类型检查,如果不是目标对象,则失败,指针失败,返回0,引用失败,抛出bad_cast类型的异常。
reinterpret_cast <new_type> (expression):低级转换,用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。
const_cast <new_type> (expression):去常量性的

explicit constructor?
为了防止类型默认转换(如:int -> class)

RTTI 是“Runtime Type Information”的缩写,意思是:运行时类型信息。它提供了运行时确定对象类型的方法。
dynamic_cast:语法形式:dynamic_cast<T>(v) ,将对象 v 转换为类型T的对象。
常用写法:
I、Poly_Derived* derivedPtr = dynamic_cast<Poly_Derived*>(ppolybase);//转换为指向Poly_Derived 型的指针,失败返回NULL;
II、Poly_Derived& derivedRef = dynamic_cast<Poly_Derived&>(polyderived); //转换为Poly_Derived 引用,失败时抛出bad_cast异常。
typeid: 语法--两种形式:typeid (type) 、typeid (expression)即任意表达式或类型名。
常见的用途:比较两个表达式的类型,或者将表达式的类型与特定类型相比较。

C函数实现 
int atoi(const char* str);
要注意几点,另外,手写代码的能力要有。

http://blog.csdn.net/zhangxinrun/article/details/6052551
stackOnly: 不许调用析构函数(private); heapOnly:不许调用new(private void*operator new(size_t))

引用和指针的区别?
http://blog.csdn.net/dujiangyan101/article/details/2844138

malloc和new的区别?

(1)malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都是程序运行中申请动态内存和释放内存的。
(2)对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器的控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理和释放内存工作的delete,new/delete不是库函数。
(3)C++程序经常调用C函数,而C程序只能用malloc/free管理动态内存。

一个C/C++编译的程序占用的内存分为以下几个部分:
1、栈区(stack):程序运行时由编译器自动分配,存放函数的参数值,局部变量值等,。其操作方式类似数据结构中的栈。程序结束时由编译器自动释放。
2、堆区(heap):在内存中开辟的另一块存储区域。一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两会事,分配方式倒类似于链表。
3、全局区(静态区)(static):编译器编译时即分配的内存。全局变量和静态变量的存储时放在一块的, 初始化的全局变量和静态变量在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域。程序结束后由OS释放。
4、文字常量区:常量字符串放在这,程序结束后由系统释放;
5、程序代码区:存放函数体的二进制代码


C++空类默认产生哪些类成员函数?(http://stackoverflow.com/questions/14868154/implicit-member-functions-of-a-class-in-c)

对于一个空类,编译器默认产生4个成员函数:

(1)默认构造函数
(2)析构函数
(3)拷贝构造函数
(4)赋值函数

不能被继承的类,如何实现?

只在heap_only stack_only?

引用和多态的区别?
C++支持两种多态性:编译时多态性,运行时多态性。 a、编译时多态性:通过重载函数实现; b、运行时多态性:通过虚函数实现。 
有virtual才可能发生多态现象; 2、不发生多态(无virtual)调用就按原类型调用(http://www.cnblogs.com/fzhe/archive/2012/12/25/2832768.html)
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
也就是说,无论只有可能继承基类的函数然后调用或发生多态,其他情况都会覆盖。


C++的多态实现机制(菱形继承虚表结构)?我的回答:编译时多态(overload),运行时多态(虚函数,override,动态绑定)
虚表是在数据常量段

C++的多态性是通过迟绑定技术来实现的(虚函数)。注意每个对象的的结构和虚函数表的结构。
http://blog.csdn.net/tujiaw/article/details/6753498
http://blog.csdn.net/jiangnanyouzi/article/details/3720807

有虚函数的类就会有一张虚函数表,多态就是通过这张表来实现的。1.默认的赋值运算符并不会操作虚函数表。2.要实现多态,必须使用指针或者引用。
引入纯虚函数的原因:1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。 2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

堆和栈的区别?http://blog.csdn.net/wwj_748/article/details/11855221


面向对象的三个特征,分别有什么作用?(http://www.cnitblog.com/Lily/archive/2006/02/23/6860.html)


虚函数的实现机制(http://blog.csdn.net/jiangnanyouzi/article/details/3720807)(http://blog.csdn.net/haoel/article/details/1948051)


结构体struct和联合体union的区别
Structure 与 Union主要有以下区别:
1)struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻,union中只存放了一个被选中的成员,而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。
2)对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了,而对于struct的不同成员赋值是互不影响的。


重载和覆盖的区别是什么?(http://www.cnblogs.com/txwsh1/archive/2008/06/28/1231751.html)
重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。覆盖(也叫重写)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数名和参数都一样,只是函数的实现体不一样。隐藏是指派生类中的函数把基类中相同名字的函数屏蔽掉了。隐藏与另外两个概念表面上看来很像,很难区分,其实他们的关键区别就是在多态的实现上。什么叫多态?简单地说就是一个接口,多种实现吧。

如果是自己为一个类写一个sizeof函数,应该考虑哪些问题。(http://blog.csdn.net/u012333003/article/details/23363827)(http://blog.sina.com.cn/s/blog_728161840100u2ib.html)

虚函数和虚继承对于一个类求sizeof的影响有什么差别


什么是堆?堆是大家共有的空间,分全局堆和局部堆。全局堆主是所有没有分配 的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。什么是栈?栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。栈是由编译器自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据结构中的栈。堆一般由程序员分配释放,若不释放,程序结束时可能由OS回收。只是可能,并非一定,所以还是一定要记得释放。这里的堆与数据结构中的堆是两回事,分配方式类似于链表。
malloc/free使用要点
a)申请了内存空间后,一定要检查是否分配成功才使用。
b)当不再需求使用这块内存时,一定要记得释放.
c)对非空内存块的释放只能释放一次
d)释放后应该把指向这块内存的指针指向NULL,防止后面的程序不小心使用了它。

C++如何动态创建二维数组(http://www.aichengxu.com/article/C++/157_4.html)

GC回收垃圾的算法么?常见的有标记-清理,标记-整理,复制算法,分代回收。(可以结合C++,Python,Java)


STL空间配置器,内存碎片管理:肯定会问这么深的?

new和malloc的区别。我说它们的一个主要区别是用new来为自定义类型对象申请空间时,会自动调用默认构造函数,但malloc只是单纯的分配内存,不会执行默认构造函数。面试官说好,现在让你设计一个带有alignment功能的malloc,申请内存的时候严格按照8byte对齐,你会怎么做?我说可以用批发——零售的方式来实现这个功能,即先申请一大块内存,然后遇到申请的时候以8byte为单位分配出去,而这一大块内存用空闲链表管理。面试官问那你设计的这个malloc系统只能管理固定的对齐度是吗,我说是。然后面试官加深了难度:如果存在不同对齐度的分配要求,该如何做?我问对齐度是不是都是2次幂,面试官说可以有这个假设。想了一下,内存管理、2次幂对齐度,就联想到伙伴系统,我说可以采取与伙伴系统类似的数据结构来管理内存,将内存区域依照不同的对齐度分组,比如说2byte对齐的region用一个链表管理,4byte对齐的region用另一个链表管理,然后遇到内存申请的时候就到相应对齐度的链表中寻找空闲区,如果相应链表没有足够的空间,可以从更高对齐度的链表中取出region然后分裂、也可以从更低对齐度的链表中取出两个region然后合并。用这种方式可以实现不同对齐度的malloc。随后我反问一个问题,问面试官这个对齐malloc的问题是凭空想出来的,还是实际开发中遇到的,面试官说在开发中确实有这种需求,为了提高cache命中率、减少缺页错误,有时候会按照对齐的方式申请内存。


解释动态绑定
实例函数通过运行时查表的方式调用,并不能在编译时确定到底调用哪个函数。照比C++效率低,但是灵活性高。

auto_ptr与shared_ptr的不同? 代码是实现。

auto_ptr:

shared_ptr可以共享,用引用计数。

线程不安全,如何实现?

Lock() UnLock()

在c++中,只要不用全局和静态变量就是线程安全的。


红黑树的介绍:

红黑树首先是一棵二叉查找树,它每个结点都被标上了颜色(红色或黑色),红黑树满足以下5个性质:
1、 每个结点的颜色只能是红色或黑色。
2、 根结点是黑色的。
3、 每个叶子结点都带有两个空的黑色结点(被称为黑哨兵),如果一个结点n的只有一个左孩子,那么n的右孩子是一个黑哨兵;如果结点n只有一个右孩子,那么n的左孩子是一个黑哨兵。
4、 如果一个结点是红的,则它的两个儿子都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
5、 对于每个结点来说,从该结点到其子孙叶结点的所有路径上包含相同数目的黑结点。

应用:map,set


const 实现机制,比如:const int i,是怎么做到i只可读的?(http://blog.csdn.net/luoyeaijiao/article/details/7982385)
简而言之,编译后const和普通变量没有区别,只是在编译的过程中,编译器会检查代码中是否有对const变量进行修改的代码,如果有则向用户报错。在编译过后,const变量就和普通变量相同了。

OFFSETOF(s, m)的宏定义,s是结构类型,m是s的成员,求m在s中的偏移量。(http://hi.baidu.com/tian_20032242/item/d43ee03be44a6ab8623affc2)

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #define OFFSET(s,m) ((size_t)&(((s*)0)->m))  

共享内存的使用实现原理 
(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?) 
将一块内存映射到两个或者多个进程地址空间。通过指针访问该共享内存区。 一般通过mmap将文件映射到进程地址共享区。 存在于进程数据段(可读写的),大小通过SHMMAX设置,缺省最大共享内存是 32 MB

内存泄露定位:http://my.oschina.net/kaixindewo/blog/28526
方法有可以用GDB,TOP命令观察,手动查找,专用的工具。

32位系统一个进程最多多少堆内存
确实是这个样子.理论上是4G. Linux实现的是 虚拟地址的前3G供给用户态的进程. 后1G是内核的部分. 也就是用户态的进程不能访问0xc0000000以上的虚拟地址.

死锁检测算法?
拓扑排序,检测环。

exit() _exit()的区别? (http://blog.csdn.net/goodlixueyong/article/details/6011021)
exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是图中的"清理I/O缓冲"一项。

Linux内存管理机制?
虚拟分页,swap分区

0 0
原创粉丝点击