C++笔记

1 篇文章 0 订阅

coding style:
    +类中定义,类外实现
    +类写在一起,方法写在一起!
    在if中,判断方式(10==n)比(n==10)要好,可以检测出是否少'='
    

以下都是编译器的
!如何判断代码是C还是C++:
#ifdef __cplusplus  

        cout<<“c++";  

#else  

        printf("c");  

#endif 
如何打印出当前源文件的文件名
    cout << __FILE__ ;
及源文件的当前行号?
    cout<<__LINE__ ;


引用类型
    引用类型在声明时必须使用变量。

const
    top-level const :表示指针本身是个const。(常指针)
    low-level const :表示指针指向一个const对象。(指针常量)
    const int *const p = &i; // right-most const is top-level, left-most is low-level;
        const int *  p = &i; 
        int const *  p = &i; //指针常量
    int *const   p = &i; //常指针

函数指针和指针函数
    函数指针是指向函数的地址的指针。
        定义:int (*funcp)(int) = func;
    指针函数是指返回类型为指针的函数。
        定义:int* func(int x,int y);kaobei


reference (&)引用类型
    1.在函数里可以操作数据本身
    2.在传入函数的时候可以防止每次开辟新的内存处理变量,节省开销。

Parameter 和 Argument(形参和实参(传入的值))

数组实参
    1.第一种方法,要求数组本身包含一个结束标记(如string,char)
    2.第二种方法,要求传入数组第一个元素和最后一个元素的指针
    3.第三种方法,传入一个数组,和表示数组大小的值。

默认参数值
    在函数声明的时候赋值。

decltype();
    获得括号里的类型
关键字extern
    extern int i;//告诉编译器,这个变量i的定义在后面。


对于智能指针:不可用于非堆内存!必须申请一个堆地址。
        析构函数会释放内存和指针置空。
unique指针:采用所有权模型,除非源是个临时右值,否则编译时报错。支持数组,支持下标运算。
share指针:采用引用计数,当最后一个指针过期时调用delete。不支持数组。
wake指针:

指针是存放地址的一个变量。
引用是一个别名,有依附性,不可改变。
*初始化的不同,*改变性的不同,*空值的不同

sizeof是编译时运行算符,可以看成一个常量。

静态局部变量作用域为 *本文件

函数传递:1值传递 2指针传递 3引用传递

短小函数,C用宏定义,C++用内联inline

加上virtual关键字,意味着将该成员函数 *声明 为虚函数
加上inline关键字,将使该函数 *实现 为内联函数。
    tips:虚函数可以启用动态联编。(在运行时进行联编工作)提高*编码效率
        内联函数提高函数的*运行效率,不可太长,不可有循环语句。

Debug   调试版本,有调试信息,不作任何优化
Release 发布版本,进行了各种优化,使得程序最优状态
Debug 因为调试代码的原因,需要相应的运行库,release则不用

断言assert
仅在debug环境下有效,如果编译为release版本则被忽略。
用于检查不应该发生的情况:int是否超出范围,字符串地址是否为空
一种安全无害的测试手段

const 与 #define(宏定义)
    const 有数据类型,编译器可以进行类型安全检查,可调试。
    define 没有数据类型,编译器不可。。。并且在字符串替换时可能会出现边际效应。
        #define N 2+2; a=N/2; //结果为a=2+2/2 = 3;记得加括号
    (内联函数也要做参数类型检查。)

有malloc/free 为什么还要 new/delete ?
    前者为库函数,后者为C++运算符。
    new/delete可以对类进行操作,在申请时调用类的构造函数和析构函数,前者不行。

C++是不是类型安全的?
    啊不是,两个不同类型的指针之间可以强制转换。

如何处理内存耗尽?
    1判断指针是否为 NULL,用return 语句终止本函数。
    2判断指针是否为 NULL,马上用 exit(1) 终止整个程序 
    3为 new 和 malloc 设置异常处理函数。例如_set_new_hander函数为new设置用户自己定义的异常处理函数,
也可以让 malloc 享用与 new 相同的异常处理函数。

判断一个操作系统是16位还是32位的?
1.使用sizeof判断指针
    int *p; cout<<sizeof(p)<<endl;//如果输出为4则为32位,结果为2则是16位。
2不能使用sizeof
    int x=65536;cout<<x<<endl;//如果输出为0则为16位,else 32.

???识别函数或指针
    在*和[]中:先与[]结合
    在*和()中:先与()结合
    需多练习

多态类中的虚函数表是 Compile-Time,还是 Run-Time 时建立的?
    *虚拟函数表是在编译期就建立了,存放各个虚拟函数的入口地址.
    *虚拟函数表指针是在运行期,也就是构造函数被调用时进行初始化的.
    (这是实现多态的关键。)

转义符'\ddd'是八进制的转义字符(d是0-7的数字)
    '\xhh'是十六进制的转义字符(h是0-9或者A-F)

内存分配的方式分三种:
    1*静态存储区域分配:在编译的时候分配好(如全局变量
    2*在栈上创建:如函数内局部变量,会在函数结束时释放掉。效率高,但容量有限。
    3*从堆上分配:也称为动态内存分配。malloc或者new申请,free或者delete释放。
    生存期1.程序整个运行期间2.函数开始到结束3.我们决定,使用非常灵活,但是问题也最多。

在比较float或double时,由于计算误差应判断两数之差是否落在区间(-e,e)内,这个e应比浮点数的精度大一个数量级。

全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的? 
    1*生命周期的不同2*内存分配区域不同3*使用范围不同
    *编译器是通过内存分配的位置来知道的。

*Heap是堆,stack是栈。 
Stack的空间由操作系统自动分配/释放,Stack空间有限,
Heap上的空间手动分配/释放,Heap是很大的自由存储区
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行

In C++, what does "explicit" mean? what does "protected" mean? 
    explicit用来修饰类的构造函数,表明该构造函数是显式的,在某些情况下,我们要求类的使用者必须显示调用类的构造函数时就需要使用 explicit,默认类型转换的话编译器会指出error。
        *注意:当类的声明和定义在两个文件的时候,explicit需要写在声明中。
    protected 控制的是一个函数对一个类的成员(包括成员变量及成员方法)的访问权限。protected成员只有该类的成员函数及其派生类的成员函数可以访问。

重复多次 fclose 一个打开过一次的 FILE *fp 指针
    *会导致文件描述符结构中指针指向的内存被重复释放,导致一些不可预期的异常。

不使用常量,直接填写数字或字符串,将有什么麻烦?
    1*可读性2*可维护性3*容易出错 

*const关键字的作用:
        1阻止变量被改变。在定义时,通常需要对它进行初始化。
        2对指针来说,可指定指针为const,也可以指定指针所指的数据为const,或二者同时指定为const;
        3在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
        4*对于类的成员函数,若指定其为const类型,则表明其是一个常函数,函数内不能修改类的成员变量;
        5*对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。
      使用:对于对象,const数据成员是不变的,对于类,const数据随实例而变。
        不能再类声明中初始化const成员,只能在类构造函数的初始化列表中进行。
        
    

关于virtual
    virtual修饰符会被隐形继承,virtual可加可不加,都能实现多态。
    当一个函数被声明为虚函数后,其派生类中的同名函数都将自动成为虚函数。
    加上可使函数更加清晰。

面向对象的三大特征:封装 继承 多态。
    *封装:客观事物都抽象成类,每个类对自身数据和方法实行protection(public,private,protected)
    *继承:三种形式:
        实现继承,指使用*基类的属性和方法而无需额外编码(继承时记得加*访问修饰符!)
            在创建子类对象时,会先调用父类的无参构造函数(有有参构造函数时,记得写个空的无参构造函数)。
            在析构子类对象时,如果有,则会先调用子类析构函数,再调用父类的析构函数!
            
        可视继承,*子窗体使用父窗体的外观和实现代码
        接口继承,仅使用属性和方法,*实现滞后到子类实现
       前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。
    *多态:是将父对象设置成为和一个或更多的与他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

重载,重写,重定义
    重载是,同一命名空间,多个同名函数,参数列表不同(包括类型,顺序,与返回类型无关)
    !重写是也叫覆盖,子类重新定义父类中有相同名称的*虚函数(多态的体现)
        注意重写的函数为virtual,相同名称参数列表类型和返回类型(除了),访问修饰符可以不用。
    重定义也叫隐藏,子类重新定义父类中有相同名称的*非虚函数,会隐藏父类的实现方法。

多态的作用
    1隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;
    2接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。

为何空类的大小为1
    每个实例都有一个独一无二的地址,为达成这个目的,编译器往往会给一个空类隐含的加一个字节。

析构函数无返回类型,没有参数,没有重载,生命周期结束,系统自动调用。
虚函数是C++多态的一种表现,可灵活进行动态绑定,以一些开销为代价。


*类中的成员默认是private的,但是可以声明public,private 和 protected,结构中定义的成员默认的都是public;
*结构和类对象都必须使用new创建。

C++中为什么用模板类?
    可用来创建动态增长和减小的数据结构。
    它是类型无关的,因此具有很高的可复用性。
    它在编译时而不是运行时检查数据类型,保证了类型安全
    它是平台无关的,可移植性强
    可用于基本数据类型

类中static成员变量只是加了访问限制的全局变量,其属性与全局变量相同。
    static成员只能在实例化后赋值,初始化列表和声明定义都不行。
    static变量的内存地址位于已初始化数据段

不能被重载的运算符 
在C++运算符集合中,有一些运算符是不允许被重载的。这种限制是出于安全方面的考虑,可防止错误和混乱。 
    不能改变 C++*内部数据类型(如 int,float 等)的运算符。 
    *不能重载‘.’,因为‘.’在类中对任何成员都有意义,已经成为标准用法。 
    不能重载目前 C++运算符集合中*没有的符号,如#,@,$等。原因有两点,一是难以理解,二是难以确定优先级。 
    对已经存在的运算符进行重载时,不能改变*优先级规则,否则将引起混乱。 

如果析构函数不是虚函数
    派生类不会调用父类析构函数,会造成内存泄露
    构造函数不能为虚,只有虚的析构函数!

《算法题》
求a,b中大的那个数(小的那个数同理)
    ( ( a + b ) + abs( a - b ) ) / 2
交换a,b两个数
    1中间值
    2加和(会有溢出风险)
    3异或(a^b)

!循环中,如果重定义了一个同名变量,则循环内使用该名字,只改变重定义的那个变量

!数组定义要求长度必须为编译期常量。

!只有在生成对象时,初始化表达式才会随相应的构造函数一起调用。
    不能在构造函数里面调用其它构造函数。

!全局对象的构造函数会在main 函数之前执行

!<<操作符的优先级是高于条件操作符?:的,在输出语句使用时,记得加括号

*static_cast<const void*>(p)
    显式强制转型将p转型为const void*型。
    在使用cout输出字符串时,需要使用,因为I/O类对<<符的重载,遇到字符型指针会当作字符串名来处理。

*在循环时,字符循环次数。

*/91题-字节中被置1的位的个数
*/92题-十六进制转十进制
*/93题-字符串逆序
*/94题-统计字符串中不同字符出现的频度
*/95题-字符串逆序
*/96题-字符串逆序


a++ 不能当左值

排序方法中关键码比较次数

左值函数
C++中模板:函数模板和类模板

下面的 throw 表达式哪些是错误的?
(a) class exceptionType { }; 
     throw exceptionType { }; 
(b) enum mathErr { overflow, underflow, zeroDivide }; 
    throw zeroDivide(); 
【标准答案】
(a) class exceptionType { }; 
     throw exceptionType();
(b) enum mathErr { overflow, underflow, zeroDivide }; 
    throw zeroDivide;


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值