剑指c++-OFFER——基础知识一

一说一下static关键字的作用

1 全局静态变量

在全局变量前加上关键字static,全局变量就定义成一个全局静态变量

内存中的位置:静态存储区,在整个程序运行期间一直都存在

初始化:未经初始化的全局静态变量会被初始化为0

作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之外开始,到文件结尾

2 局部静态变量

在局部变量前加上关键字static,局部变量就变成一个局部静态变量

内存中的位置:静态存储区

初始化:未经初始化的局部静态变量会被自动初始化为0

作用域:作用域仍然为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存中,只不过我们不能在对他进行访问,直到该函数再次被调用,并且值不变。

3静态函数

在函数返回类型前加上static,函数就被定义为静态函数,函数的声明和定义在默认情况下都是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

函数的实现使用static修饰,那么这个函数只可在本cpp内使用,不会同其他cpp中的同名函数引起冲突。

warning:不要在头文件中声明static的全局函数,不要在cpp内声明非static的全局函数,如果你要在多个cpp中复用该函数,就把它的声明提到头文件里去,否则cpp内部声明需加上static修饰。

4类的静态成员

在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性,因此,静态成员是类的所有对象中的共享成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共有。

5类的静态函数

静态成员函数和静态数据成员一样,他们都属于类的静态成员,他们都不是对象成员,因此,对静态成员的引用不需要用对象名。

在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);

二 说一下C++与C的区别

c++是面向对象语言,c是面向过程的语言

c++具有封装、继承、多态三种特性

c++相比于c,增加多种类型安全的功能,如强制转换

c++支持范式编程,如模板类、函数模板

三 指针和引用

1引用:

c++是c语言的继承,他可进行过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以进行继承和多态为特点的面向对象的程序设计。引用就是c++对c语言的重要扩充。引用就是某一变量的一个别名,对引用的操作与变量

操作完全一样,引用的声明方法:类型标识符&引用名=目标变量名;引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了

2 指针:

指针利用地址,它的值直接指向存在电脑存储器中另一个地方的值,由于通过地址能找到所需的变量单元,剋说,地址指向该变量单元。因此,将地址形象化的成为指针,意思是通过它能找到以它为地址的内存单元。

区别:

1、指针有自己的一块空间,而引用是一个别名;

2、使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小

3、指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象的引用;

4、作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接引用的修改都会改变引用所指向的对象;

5、可以有const指针,但是没有const引用

6、 指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能被改变;

7、指针可以有多级指针,而引用只能一级

8、如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏

9、指针和引用使用++运算符的意义不一样

变量:申明一个变量的时候,计算机会将指定的一块内存空间与变量名进行绑定

例:int x=5;将5赋值给名字叫做x的内存空间,本质是将值5赋值到一块内存空间,而这个内存空间名叫做x过

变量在内存中的操作是经过2个步骤

1》找出与变量名相对应的内存地址

2》根据找到的地址,取出该地址对应的内存空间里面的值进行操作

指针的结构和原理

指针变量和任何变量一样,也有变量名,是这个变量名对应的内存空间,特殊之处:指针变量相对应的内存空间存储的值恰好是某个内存地址。

int x=5;int *ptr=&x;

变量名仅仅是一块内存空间的名字,我们应该关心的是这些变量名相对应的内存地址。

指针变量和任何变量在内存中的形式是相同的,仅在于其存储的值比较特殊。

引用:尤其是在1作为函数参数的时候,需要在函数内部修改更新函数外部的值的时候,

int x=5;int &y=x;

区别 1引用不要解引用即可直接获取到指向的内存空间的值。

        2 引用的赋值操作也不需要取地址符来赋值,可以直接通过变量名,int &y=x,而不需要 int&y=&x

        3引用在申明的时候要有就必须要有初始值,而且引用变量指向的内存地址是不能变化,不像指针那样可以很灵活的重新指向其他地址

 

4 指针在数组中的应用和注意事项

在c++中,一个Array类型的变量arr,其实本质是一个指向数组第一个元素的指针。字符串string在c++中其实就是char类型的array,例如:char arr[] = {'a','b','c','d','e','\0'};这就是表示的一串字符串“abcde”,其中arr[0],arr[1], arr[2]..........之间相差的数值可能并不一定是1byte, 要根据这个数组的类型来判断,compiler会自动判断它们之间的相差值的; 另外在c++中字符串也可以用string literals(求大神翻译)的方式表示,即:char *arr2 = "abcde"; 但是通过string literal方式表示的字符串是read only的,不能修改的, 例如:*(arr2+1)= 'f'; 这句语句会产生error的。其在内存中的表现形式如下图所示:

指针不能dereference的情况

但一个指针的值是invalid的时候,那么这个指针是不能dereference的。那么到底哪几种情况是invalid的呢?主要有以下几种情况:

1)当这个指针的值是NULL的时候,这个指针是不能dereference的。因为指针为NULL,即表示这个指针指向内存地址为0的地址块,内存地址为0的内存空间是没有值的,所以是不能dereference的; 例如:int *ptr = NULL; cout<<*ptr<<endl; 是错误的。

2)当某个指针被deallocte或者某个指针所在的内存空间被erase了的话,那么这个指针也是不能被dereference的;例如下面的代码:

int *function(int a){
    
    int temp = 5;
    return &temp;
}

上面的代码返回的指针也是不能dereference的,因为temp出了作用域后会被系统回收这一块空间,temp所占的内存空间已经被erase了,所以它返回的指针是一个指向被erase了的内存空间。也是不能dereference的,否则会出错。编译阶段会给出警告,在runtime的时候,如果dereference是会有error的。

好了C++的指针(pointer)和引用(reference)就先总结到这里了。

四给定三角形ABC和一点P(x,y,z),判断点P是否在ABC内,给出思路并手写代码

根据面积法,如果P在三角形ABC内,那么三角形ABP的面积+三角形BCP的面积+三角形ACP的面积应该等于三角形ABC的面积。算法如下:

#include<iostream>

#include<math.h>

using namespace std;

#define ABS_FLOAT_0 0.0001

struct point_float

{

  float x;

  float y;

};

//计算三角形面积

float GetTriangleSquar(const point_float pt0, const point_float pt1, const point_float pt2)

{

   point_float AB,BC;

  AB.x=pt1.x-pt0.x;

  AB.y=pt1.y-pt0.y;

  BC.x=pt2.x-pt1.x;

  BC.y=pt2.y-pt1.y;

  return fabs(AB.x*BC.y-AB.y*BC.x)/2.0f;

}

//判断给定一点是否在三角形内或边上

bool IsInTriangle(const point_float A,const point_float B,const point_float C,const point_float D)

{

float SABC,SADB,SBDC,SCDA;

SABC = GetTriangleSquar(A, B, C);

SADB = GetTriangleSquar(A, D, B);

SBDC = GetTriangleSquar(B, D, C);

SCDA = GetTriangleSquar(C D, A);

float SumSuqar=SADB+SBDC+SADC;

 

if ((-ABS_FLOAT_0 < (SABC - SumSuqar)) && ((SABC - SumSuqar) < ABS_FLOAT_0))

{

return true;

}

else

{

return false;

}

}

怎么判断一个数是二的倍数,怎么求一个数中有几个1,说一下你的思路并手写代码

1 判断一个数是不是二的倍数,即判断该数二进制末位是不是0;

a%2==0或者a&0x0001==0

求一个数中1的位数,可以直接诸位除十取余判断

int fun (long x)

{

    int  _const=0;

    while(x)

  {

     if(x%10==1)

    {

      _const++;

      x=x/10;

    }

 return _const;

   }

}

int main()

{

  cout<<fun(123321)<<endl;

  return 0;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值