c++常用知识点,易错点,面试常问点

1.谈谈你对C++内存分配的理解


1.1 还是的先看看C++对内存分为哪几个区?


1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。想知道为什么效率高吗?因为关于栈的操作如push集成在处理器的指令集中,效率很高,但是分配的内存容量有限。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 
4、文字常量区—常量字符串就是放在这里的。
5、程序代码区—存放函数体的二进制代码。



1.2 再给面试官谈谈new/delete和malloc/free的区别?  


1、像我们的new/delete和malloc/free就是在上面所说的堆区上操作。程序员申请了内存,用完要记得释放,否则就内存泄露了。而且多次申请释放,会造成堆区碎片,这个需要注意下。
2、new/delete是操作符,而malloc/free是函数。前者可以被重载。前者可以有构造函数和析构函数。前者返回的某种类型对象的指针,后者返回VOID指针。


2.基于问题1,深入谈谈堆和栈


1、申请方式:


栈:函数内的局部变量:int a = 10;
堆:new / malloc

2、申请后的系统响应:


栈:只要申请的空间大小<栈的剩余空间,栈就分配。
堆:因为new,malloc都是C++封装的,里面做了这样的事:首先明白windows有这么一个记录空闲空间地址的链表,C++遍历该链表,先找到第一个空闲空间大小大于程序员申请的空间大小的地址(堆节点),将该堆节点从链表中删除,把该节点的空间分配给程序。对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

3、申请大小:


栈:默认是1M?还是2M?
堆:看系统的虚拟内存有多大了。(请记住堆是一个节点为空闲内存空间的链表。。)堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

4、申请效率:


栈:速度快,push,pop等指令都内置在处理器了,能不快吗?
堆:相对慢(为什么慢,可以看2,就知道它在申请的时候干了多少事),还容易产生内存碎片。不过容量大,操作方便。

5、存储内容:


栈(依次是):
主函数中后的下一条指令地址
然后是函数的各个参数(在大多数的C编译器中,参数是由右往左入栈的)
函数中的局部变量
堆:程序员随意安排。

6、存取效率:


先看看这段代码
    int main(){  char a = 1;  char c[] = "1234567890";  char *p ="1234567890";  a = c[1];  a = p[1];  return 0;  }  

这是在函数内,char数组c,是在栈上。
char *p = "1234567890" ,其中虽然*p也是在栈上,但是"1234567890"在常量区。

再看看它们对应的汇编代码:
    10: a = c[1];  00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]  0040106A 88 4D FC mov byte ptr [ebp-4],cl  11: a = p[1];  0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]  00401070 8A 42 01 mov al,byte ptr [edx+1]  00401073 88 45 FC mov byte ptr [ebp-4],al  
可以看到在栈上的c[]只要两行就能取到内容,而p要先去把常量区的内容放到edx中,再存取。
说明纯栈操作,效率是要高一些的。

7、总结


看看一个经典代码就什么都懂了:
  1. //main.cpp   
  2. int a = 0; //全局初始化区   
  3. char *p1; //全局未初始化区   
  4. main()   
  5. {   
  6.     int b; //栈   
  7.     char s[] = "abc"//栈   
  8.     char *p2; //栈   
  9.     char *p3 = "123456"//123456\0在常量区,p3在栈上。   
  10.     static int c =0; //全局(静态)初始化区   
  11.     p1 = (char *)malloc(10);   
  12.     p2 = (char *)malloc(20);   
  13.     //分配得来得10和20字节的区域就在堆区。   
  14.     strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。   
  15. }   
[cpp] view plain copy
  1. //main.cpp   
  2. int a = 0; //全局初始化区   
  3. char *p1; //全局未初始化区   
  4. main()   
  5. {   
  6.     int b; //栈   
  7.     char s[] = "abc"//栈   
  8.     char *p2; //栈   
  9.     char *p3 = "123456"//123456\0在常量区,p3在栈上。   
  10.     static int c =0; //全局(静态)初始化区   
  11.     p1 = (char *)malloc(10);   
  12.     p2 = (char *)malloc(20);   
  13.     //分配得来得10和20字节的区域就在堆区。   
  14.     strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。   
  15. }   





3.谈谈这strcpy,memcpy和sprintf三者的区别?


共同点:都是拷贝东西。
效率排行: memcpy > strcpy > sprintf
操作对象:memcpy是两块内存之间的操作,strcpy 是两个字符串对象之间的操作,sprintf是任意类型转到字符串的操作。


4.C++多态机制


先上代码:
[cpp] view plain copy
  1. #include <iostream.h>  
  2. class animal  
  3. {  
  4. public:  
  5.     void sleep()  
  6.     {  
  7.         cout<<"animal sleep"<<endl;  
  8.     }  
  9.     void breathe()  
  10.     {  
  11.         cout<<"animal breathe"<<endl;  
  12.     }  
  13. };  
  14.   
  15. class fish:public animal  
  16. {  
  17. public:  
  18.     void breathe()  
  19.     {  
  20.         cout<<"fish bubble"<<endl;  
  21.     }  
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     fish fh;  
  27.     animal *pAn=&fh;  
  28.     pAn->breathe();  
  29.     return 0;  
  30. }  
[cpp] view plain copy
  1. #include <iostream.h>  
  2. class animal  
  3. {  
  4. public:  
  5.     void sleep()  
  6.     {  
  7.         cout<<"animal sleep"<<endl;  
  8.     }  
  9.     void breathe()  
  10.     {  
  11.         cout<<"animal breathe"<<endl;  
  12.     }  
  13. };  
  14.   
  15. class fish:public animal  
  16. {  
  17. public:  
  18.     void breathe()  
  19.     {  
  20.         cout<<"fish bubble"<<endl;  
  21.     }  
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     fish fh;  
  27.     animal *pAn=&fh;  
  28.     pAn->breathe();  
  29.     return 0;  
  30. }  

运行结果是:


内存模式:

子类fish的内存模型是,先animal,然后再自己增加的部分。因为:
animal *pAn=&fh;
fish对象被强制更改成父类animal对象,指针指向fish的上半部分(那不就是一个animal对象了吗?),所以pAn->breathe()就是父类的breathe()。

更深入的了解机制(早绑定和晚绑定):


早绑定:C++在编译的时候,要确定每个对象调用的函数的地址,这就是早绑定。
晚绑定:编译的时候先不决定,等到运行的时候,再根据情况确定要调用的函数地址,这就是晚绑定。

什么东西支持晚绑定这个机制呢?虚函数!
虚函数机制,每个类对象有个虚表指针:vptr,这个指针指向类所属的虚表:vtable。

当我们把父类animal的breathe()设置为虚函数,子类fish即使被强制转换成animal对象,也是没关系的。
因为pAn实际指向的就是fish对象!
因此vptr指向的是fish的vtable!
所以vptr指向的vtable中的breathe()函数就是fish对象的breathe()函数。

正确的多态代码:
[cpp] view plain copy
  1. #include <iostream.h>  
  2. class animal  
  3. {  
  4. public:  
  5.     void sleep()  
  6.     {  
  7.         cout<<"animal sleep"<<endl;  
  8.     }  
  9.     virtual void breathe()  
  10.     {  
  11.         cout<<"animal breathe"<<endl;  
  12.     }  
  13. };  
  14.   
  15. class fish:public animal  
  16. {  
  17. public:  
  18.     void breathe()  
  19.     {  
  20.         cout<<"fish bubble"<<endl;  
  21.     }  
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     fish fh;  
  27.     animal *pAn=&fh;  
  28.     pAn->breathe();  
  29.     return 0;  
  30. }  
[cpp] view plain copy
  1. #include <iostream.h>  
  2. class animal  
  3. {  
  4. public:  
  5.     void sleep()  
  6.     {  
  7.         cout<<"animal sleep"<<endl;  
  8.     }  
  9.     virtual void breathe()  
  10.     {  
  11.         cout<<"animal breathe"<<endl;  
  12.     }  
  13. };  
  14.   
  15. class fish:public animal  
  16. {  
  17. public:  
  18.     void breathe()  
  19.     {  
  20.         cout<<"fish bubble"<<endl;  
  21.     }  
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     fish fh;  
  27.     animal *pAn=&fh;  
  28.     pAn->breathe();  
  29.     return 0;  
  30. }  

运行结果:


再一次深入了解vptr和vtable:


每个含有virtual function的类中都隐式包含着:
一个静态虚指针vfptr指向该类的静态虚表vtable
vtable中的表项指向类中的每个virtual function的入口地址

每个类内部都有一个虚表,无论类型怎么被转换,虚表指针vptr都是固定的。(fish被转换成animal也无所谓,vptr指向的永远是fish的vtable)

关于虚表:
1、每一个类都有虚表。
2、虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。如果基类3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会有虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。
3、派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同


5.C++的虚函数和纯虚函数


1、后者不可实例化:虚函数和纯虚函数可以定义在同一个类中,含有纯虚函数的类被称为抽象类,而只含有虚函数的类不能被称为抽象类(抽象类不可实例化)。

2、后者不可被直接使用:虚函数可以被直接使用,也可以被子类重载以后,以多态的形式调用,而纯虚函数必须在子类中实现该函数才可以使用,因为纯虚函数在基类有声明而没有定义

3、两者都是可以被重载,体现多态:虚函数和纯虚函数都可以在子类中被重载(虚函数可以不被重载,纯虚函数必须在子类实现),以多态的形式被调用。

4、形式上:virtual{};纯虚函数的定义形式:virtual  { } = 0;在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时要求前期绑定,然而虚函数却是动态绑定,而且被两者修饰的函数生命周期也不一样。(vitrual 和 static 就是死对头

5、意义上:定义纯虚函数就是为了让基类不可实例化(没意义),因为实例化这样的抽象数据结构本身并没有意义或者给出实现也没有意义。



个人感觉,很多时候,基类,它能够实例化对象就是个不合理的存在,比如:动物,你给我实例化一个动物看看?


6.引用ref


1、什么是“引用”?声明和使用“引用”要注意哪些问题?


引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。声明一个引用的时候,切记要对其进行初始化。
引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。
声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。

2、将“引用”作为函数参数有哪些特点?


(1)传递引用给函数与传递指针的效果是一样的。
这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;(无需副本
而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。

(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。(阅读障碍啊


3、什么时候用“常引用"?


const 类型标识符 &引用名=目标变量名;
[cpp] view plain copy
  1. int a ;  
  2. const int &ra=a;  
  3. ra=1; //错误  
  4. a=1; //正确   
[cpp] view plain copy
  1. int a ;  
  2. const int &ra=a;  
  3. ra=1; //错误  
  4. a=1; //正确   
既要保证效率,又要保证传递的数据不能被改变。

[cpp] view plain copy
  1. string foo( );  
  2. void bar(string & s);   
  3. bar(foo( )); //错误  
  4. bar("hello world");//错误   
[cpp] view plain copy
  1. string foo( );  
  2. void bar(string & s);   
  3. bar(foo( )); //错误  
  4. bar("hello world");//错误   
因为bar中参数是非const类型,而string的临时对象都是const类型,所以把const类型对象赋值给非const类型对象,是编译不过的。


4、将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?


(1)不能返回局部变量的引用。
主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。 

(2)不能返回函数内部new分配的内存的引用。
虽然不存在局部变量的被动销毁问题,可是有出现了其他问题:
被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak


(3)流操作符重载返回值声明为引用 【必须用引用】
估计就是C++引入”引用“这个概念主要原因吧。
流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。
为什么不是流对象呢?
每次返回值都是一个流对象的话,都要一次拷贝构造函数,每次的<< 都是不同的流对象,从开销和效率上看,这显然不可取。
为什么不是流对象指针呢?
指针能<<连续两次吗?如果针对流对象能的话,要修改整个指针机制,这显然不可取。
所以流对象引用,才是唯一可取的方法!

(4)赋值操作符 = 返回值也是声明为引用【必须用引用】
因为它和流操作符一样,都可以连续操作: x = y = 1。用引用,很科学。理由如(3)。


(5)四则运算符 + - * /  的返回值不能使引用【必须不能用引用】
主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:
返回一个对象、
返回一个局部变量的引用、
返回一个new分配的对象的引用、
返回一个静态对象引用。
根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。
所以可选的只剩下返回一个对象了。


5、引用与多态的关系?


引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。
[cpp] view plain copy
  1. Class A;   
  2. Class B:Class A{...};    
  3. B b;   
  4. A& ref = b;  
[cpp] view plain copy
  1. Class A;   
  2. Class B:Class A{...};    
  3. B b;   
  4. A& ref = b;  


6、引用与指针的区别?

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。
程序中使用指针,程序的可读性差;
而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
此外,就是上面提到的对函数传ref和pointer的区别。


参考资料:http://blog.csdn.net/wfwd/archive/2006/05/30/763551.aspx


7.实现strcpy


[cpp] view plain copy
  1. char *strcpy(char *strDest, const char *strSrc)  
  2. {  
  3.     if ( strDest == NULL || strSrc == NULL)  
  4.         return NULL ;  
  5.     if ( strDest == strSrc)  
  6.         return strDest ;  
  7.     char *tempptr = strDest ;  
  8.     while( (*strDest++ = *strSrC++) != ‘\0’)  
  9.     ;  
  10.     return tempptr ;  
  11. }  
[cpp] view plain copy
  1. char *strcpy(char *strDest, const char *strSrc)  
  2. {  
  3.     if ( strDest == NULL || strSrc == NULL)  
  4.         return NULL ;  
  5.     if ( strDest == strSrc)  
  6.         return strDest ;  
  7.     char *tempptr = strDest ;  
  8.     while( (*strDest++ = *strSrC++) != ‘\0’)  
  9.     ;  
  10.     return tempptr ;  
  11. }  


8.实现String类


一直都有这么一个印象:拷贝构造函数和赋值函数是一对好基友

[cpp] view plain copy
  1. class String  
  2. {  
  3. public:  
  4. String(const char *str = NULL); // 通用构造函数  
  5. String(const String &another); // 拷贝构造函数  
  6. ~ String(); // 析构函数  
  7. String & operater =(const String &rhs); // 赋值函数  
  8. private:  
  9. char *m_data; // 用于保存字符串  
  10. };  
  11.   
  12. String::String(const char *str)  
  13. {  
  14.    if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断  
  15.      {  
  16.        m_data = new char[1] ;  
  17.        m_data[0] = '\0' ;  
  18.      }  
  19.    else  
  20.     {  
  21.        m_data = new char[strlen(str) + 1];  
  22.        strcpy(m_data,str);  
  23.     }  
  24. }   
  25.   
  26. String::String(const String &another)           //拷贝构造函数  
  27. {  
  28.     m_data = new char[strlen(another.m_data) + 1];  
  29.     strcpy(m_data,other.m_data);  
  30. }  
  31.   
  32. String& String::operator =(const String &rhs)   //赋值函数    
  33. {  
  34.     if ( this == &rhs)  
  35.         return *this ;  
  36.     delete []m_data; //删除原来的数据,新开一块内存  
  37.     m_data = new char[strlen(rhs.m_data) + 1];  
  38.     strcpy(m_data,rhs.m_data);  
  39.     return *this ;  
  40. }  
  41.   
  42. String::~String()  
  43. {  
  44.     delete []m_data ;  
  45. }  
[cpp] view plain copy
  1. class String  
  2. {  
  3. public:  
  4. String(const char *str = NULL); // 通用构造函数  
  5. String(const String &another); // 拷贝构造函数  
  6. ~ String(); // 析构函数  
  7. String & operater =(const String &rhs); // 赋值函数  
  8. private:  
  9. char *m_data; // 用于保存字符串  
  10. };  
  11.   
  12. String::String(const char *str)  
  13. {  
  14.    if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断  
  15.      {  
  16.        m_data = new char[1] ;  
  17.        m_data[0] = '\0' ;  
  18.      }  
  19.    else  
  20.     {  
  21.        m_data = new char[strlen(str) + 1];  
  22.        strcpy(m_data,str);  
  23.     }  
  24. }   
  25.   
  26. String::String(const String &another)           //拷贝构造函数  
  27. {  
  28.     m_data = new char[strlen(another.m_data) + 1];  
  29.     strcpy(m_data,other.m_data);  
  30. }  
  31.   
  32. String& String::operator =(const String &rhs)   //赋值函数    
  33. {  
  34.     if ( this == &rhs)  
  35.         return *this ;  
  36.     delete []m_data; //删除原来的数据,新开一块内存  
  37.     m_data = new char[strlen(rhs.m_data) + 1];  
  38.     strcpy(m_data,rhs.m_data);  
  39.     return *this ;  
  40. }  
  41.   
  42. String::~String()  
  43. {  
  44.     delete []m_data ;  
  45. }  


9.#include<file.h> 与 #include "file.h"的区别?


答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。


10.C++用C编译器编译后的函数为什么要加入extend "C"?


两者编译机制不一样,为了能够和谐工作,extend "c"告诉C++编译器,这里按照C编译器的处理方式编译链接就行了。
一句话:实现C++与C及其它语言的混合编程。
(我在JNI的时候用到这玩意~)

为什么?

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。
函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为: 
void foo( int x, int y );  
该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。

现在假设模块A是C语言编译后的,模块B是C++模块。B中调用A的函数。

这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;
它会在连接阶段中从模块A编译生成的目标代码中找到此函数。



11.面向对象的三个基本特征,并简单叙述之?


1. 封装:


将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)

2. 继承:


广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。

3. 多态:


是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。


12. 重载(overload)和重写(overried)的区别?


从定义上来说:


重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
重写:是指子类重新定义父类虚函数的方法。

从实现原理上来说:


重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!

重写:和多态真正相关当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。


13. 如何判断一段程序是由C 编译程序还是由C++编译程序编译的?

[cpp] view plain copy
  1. #ifdef __cplusplus  
  2. cout<<"C++";  
  3. #else  
  4. cout<<"c";  
  5. #endif  
[cpp] view plain copy
  1. #ifdef __cplusplus  
  2. cout<<"C++";  
  3. #else  
  4. cout<<"c";  
  5. #endif  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用ACS来实现AAA服务

ACS简介思科安全访问控制服务器&#xff08;Cisco Secure Access Control Sever&#xff09;是一个高度可扩展、高性能的访问控制服务器&#xff0c;提供了全面的身份识别网络解决方案&#xff0c;是思科基于身份的网络服务(IBNS)架构的重要组件。Cisco Secure ACS通过在一个集…

C/C++二维数组名和二级指针的联系与区别

1. 指针 1.1 一个指针包含两方面&#xff1a;a) 地址值&#xff1b;b) 所指向的数据类型。 1.2 解引用操作符&#xff08;dereference operator&#xff09;会根据指针当前的地址值&#xff0c;以及所指向的数据类型&#xff0c;访问一块连续的内存空间&#xff08;大小由指针所…

BN层

论文名字&#xff1a;Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 论文地址&#xff1a;https://arxiv.org/abs/1502.03167 BN被广泛应用于深度学习的各个地方&#xff0c;由于在实习过程中需要修改网络&#xff0c;修改的…

深入浅出 Javascript API(二)--地图显示与基本操作 转

深入浅出 Javascript API&#xff08;二&#xff09;--地图显示与基本操作 地图显示与基本操作&#xff08;放大、缩小、移动、坐标显示&#xff09;是JavascriptAPI的基本功能&#xff0c;也是一个WebGIS应用的基本内容&#xff0c;Javascript提供了非常便捷的开发方法&#x…

关于SQL数据库中cross join 和inner join用法上的区别?

使用mysql创建两张表 表a 表b 可以使用下面的脚本创建表&#xff0c;并且添加测试数据&#xff1a; CREATE TABLE a ( name varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, sex varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL D…

把数组排成最小的数

题目&#xff1a;输入一个正整数数组&#xff0c;将它们连接起来排成一个数&#xff0c;输出能排出的所有数字中最小的一个。 举例&#xff1a;输入数组{32, 321},则输出这两个能排成的最小数字32132。请给出解决问题的算法&#xff0c;并证明该算法。 答&#xff1a;算法如下&…

VS 使用 :新建项目

1.文件位置不放C盘 转载于:https://www.cnblogs.com/duanshouchang/p/10431829.html

Activit系列之---Activity的生命周期

Activity的生命周期 Hello,巴友们好&#xff0c;小菜我又来发博文啦。上篇文章给大家简单的介绍了一下Activity&#xff0c;以及如何创建一个最简单的Activity并且在上面显示hello android! 我们知道要创建一个自己的Activity就必须继承Activity这个类&#xff0c;并且实现它的…

CAP定理以及证明

历史 这个定理起源于柏克莱加州大学University of California, Berkeley的计算机科学家埃里克布鲁尔在2000年的分布式计算原则研讨会&#xff08;Symposium on Principles of Distributed Computing&#xff08;PODC&#xff09;&#xff09;上提出的一个猜想。 在2002年&…

java线程自带队列的使用以及线程阻塞

java线程&#xff0c;设置队列的大小实现队列阻塞 public class QueueThreads {private static int nThreads 4;//Runtime.getRuntime().availableProcessors() * 2 1;private static BlockingQueue<Runnable> queue new ArrayBlockingQueue<Runnable>(4);//队列…

ASP.NET下QueryString不同字符编码间强制转换的解决方案

正常的情况下&#xff0c;现在asp.net的网站很多都直接使用UTF8来进行页面编码的&#xff0c;这与Javascript、缺省网站的编码是相同的&#xff0c;但是也有相当一部分采用GB2312。对于GB2312的网站如果直接用javascript进行ajax数据提交&#xff0c;例如&#xff1a;http://ww…

ASP.NET MVC3 异步刷新

ASP.NET MVC3 异步刷新2011-08-13 09:51:53标签&#xff1a;MVC3 异步刷新 休闲 N Layer 职场原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://leelei.blog.51cto.com/856755/638408好久没…

编译rocksdb源码导致的部署失败

这几天经历了一次心酸的历程&#xff0c;使用了rocksdb第三方库&#xff0c;编译器是7.2&#xff0c;rocksdb是20190701从github上取下来的&#xff0c;由于rocksdb自己的CMakeList.txt中使用了-marchnative编译参数&#xff0c;强制使用了编译代码服务器的cpu指令集&#xff0…

检测APK是否混淆

目录 为什么要检测APK是否混淆混淆的优点混淆的缺点APK的混淆的分类检测工具检测人工检测自动化检测为什么要检测APK是否混淆 apk代码混淆就是为了保护代码安全&#xff0c;防止被反编译拿到源码做审计找出危险漏洞&#xff0c;现在大部分的APK都会做混淆。 下面分析混淆APK后的…

基于asp.net的Web开发架构探索(转)

问题由来 最近在研究适合团队开发的web架构解决方案&#xff0c;该架构即要适合分工协作又要有一定扩展性&#xff0c;适合不同的数据库需要&#xff0c;因此我查阅了一些资料&#xff0c;初步构想出了一套架构&#xff0c;请各位多多指教。 探索 web开发架构最经典莫过于三层架…

SkipList 以及高度的确定

转载&#xff1a;https://www.cnblogs.com/lnlvinso/p/8848883.html 结果&#xff1a;skiplist的高度是个随机值。 SkipList理解 记下自己对跳表SkipList的理解。 SkipList采用空间换时间的思想&#xff0c;通过增加数据间的链接&#xff0c;达到加快查找速度的目的。 数据库L…

IIS AppCreate子目录的错误(0x80020006)

这几天做了升级用的安装包,需要在原来的ASP 的虚拟目录下&#xff0c;再创建一个新的ASPNet 虚拟目录。上网查了C# iis设定的资料&#xff0c;按照上面一路做下来&#xff0c;还是无法成功过。 代码只有两行&#xff0c;如下&#xff1a;DirectoryEntry siteVDir new Director…

网络通信TCP协议三次握手

刚刚看linux公社看见里面一个讲TCP的文章&#xff0c;文章讲的很有意思生动形象&#xff0c;很有助于对TCP协议的理解和掌握&#xff0c;所以转载过来方便以后看一下HAHA~~~TCP是什么? TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的、可靠的、 …

Android入门逆引手册 - 12 评分条(RatingBar)的使用

这里介绍评分条android.widget.RatingBar类的使用。 ● 评分&#xff08;星&#xff09;的最大数的设置&#xff0c;调用setNumStars()方法。● 现在的评分的设置&#xff0c;调用setRating()方法。 例程源码(Java)[java]RatingBar ratingBar (RatingBar)findViewById(id.rati…

数据库事务的四大特性以及事务的隔离级别

本篇讲诉数据库中事务的四大特性&#xff08;ACID&#xff09;&#xff0c;并且将会详细地说明事务的隔离级别。 如果一个数据库声称支持事务的操作&#xff0c;那么该数据库必须要具备以下四个特性&#xff1a; ⑴ 原子性&#xff08;Atomicity&#xff09; 原子性是指事务包含…