欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++难点记录

程序员文章站 2024-03-19 09:25:34
...

预编译

-#line

-#error
加打印错误信息(不用加"")

-#proram

debug:调试版本,内有调试代码和库 release:发行版本,优化,紧凑

  • 函数默认值

    • 有声明写在声明,没声明写在定义

        int a(int b=1);
      
    • 第一个默认值参数后右边全部要加默认值

    • 重载时如果前面相同参数而后面不同参数设置默认值会导致错误

  • typedef

    • 定义数据类型,可以int等 也可以struct等

      typedef int p
      p a=10;

    • 分析方法:由变量名出发先右看,后左看,一个一个圆括号跳出

    • 用于简化相同重复的复杂定义

类型不安全(指针的类型的强制转换)

  • 联合

    • 共用一段地址
    • 一个成员被赋值时其他成员被重写
  • 引用(reference)

    • 不能建立数组的引用
    • 可以用于传递给函数的数据较大时
    • 在主调函数的调用点处,必须用变量的地址作为实参
    • 不能返回局部变量
    • 返回引用,需在函数名前加&,return处不用加& 接收的加不加都行
    • 经常操作一个对象的操作符的重载的返回值
    • 使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。
    • 作为成员变量不能赋值来初始化,要用初始化列表

sizeof是编译时运算符

  • 指针

    • 用指针创建的常量数组不能修改其数组成员的值
      new delete
  • const

    • 只能在定义的文件中使用,定义的对象不能修改其值,引用对象可以是不同但相关类型(E:int和float,其间会产生中间变量,实际是对该中间变量)

    • 动态数组必须初始化

    • 类必须提供默认构造函数

    • 指向常量指针(指向const对象的指针),可以重新赋值,使指向其他const对象,必须初始化,

        	const double *cptr;//是cptr指向的对象为const,不是指针为const	
      
    • const对象的地址不能给非const指针(void也适用)

    • 非const对象的地址可以赋给const对象的指针,但不能通过const对象的指针修改该对象(他原先的指针可以修改自己)

    • 常指针:指向const对象的const指针,指针的值不能改

        double *const pi_ptr = ...;
      
    • 指向常量的常指针

        const *const pi_ptr = ...;
      
    • 在类中不会修改数据成员的函数都应该声明为const即为常成员变量,编写时修改类数据成员,提高程序健壮性

        类型说明符 函数名(参数列表) const;//声明和定义都要加const
      
    • 只有常成员变量才能操作常量或常对象

    • 函数的形参为const类型

    • const &a=b; 不能通过a的值修改地址下的值,但可以修改B

    • const成员变量初始化用初始化列表,不能用赋值

    • 在内存中只有一个拷贝

    • const修饰指针为顶层指针,修饰所指对象为底层指针

    • const_cast 改变运算对象的底层const

        int *p_f = const_cast<int *>(p_e)
      
    • 类里的数据成员只能在构造函数中用列表初始化,在构造函数执行初始化完才赋予const属性

  • const_casr

    • 属于强制类型转换
    • 用于函数的形参非const,在不修改const变量值的前提下将const变量作为传参
    • 用于指向const变量的指针指向了非const变量,无法通过该指针修改变量值的情况
  • define

    • 在内存中有多份拷贝,比const占空间
    • 无论在哪里定义都为全局
  • 数组

    • 数组作为函数的参数传递时,数组会退化为定义数组类型的指针,sizeof取得其类型的大小
    • 数组名赋值给指针也会退化为数组类型的指针
    • sizeof数组名 得到其大小数组数*类型
    • 定义数组必然创建新空间
    • 旧编译器不能用变量当下标定义,新的有些可以
      extern
      -extern conut 能在所有文件中使用,其他类型默认加了extern
      -一个文件中定义,头文件中声明,多个文件使用
      -声明在函数体中时不能被初始化
      -相当于声明未解决符号表

volatile:编译器做优化会把变量值存放到别处访问,而该关键字使代码每次都从原地址访问

-  1). 并行设备的硬件寄存器(如:状态寄存器)

-  2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

-  3). 多线程应用中被几个任务共享的变量
  • mutable

    • 用于被const修饰函数也可以修改非成员变量,需将该变量用mutable修饰(如const般)
  • 枚举

    • 枚举常量的序号默认从0
    • 序号号指定值后依次加一,前的按默认排序,序号可重复
    • 枚举产量只能以标识符形式,不能整数型字符型等
    • 可进行关系运算、赋值、输出,都是以其序号为数据

指针

只能使用指向常量的指针来存放常量对象的地址

运算

  • 判断执行顺序

    1. 优先级

    2. 结合顺序

       C语言中具有右结合性的运算符包括所有单目运算符以及赋值运算符(=)和条件运算符。其它都是左结合性
       结合性是在相同优先级时判断哪个运算符先执行
      

类 和 结构体

  • eplicit 使显式

      class A{A(int a);A(float a)}
      A a = 20; //相当于给A的对应构造函数(A (int a))传入20,为隐式
    
  • 初始化列表

    • 基类有带参构造函数,派生类对其初始化不能用赋值

    • 基类有数据成员,派生类对其初始化不能用赋值

    • 对于数据密集型,比构造函数赋值更高效

    • 还有这种用法:Point::Point(T a,T b):x(a),y(b){} x,y为成员变量

      class A{
      int a;
      float b;
      A():a(20),b(1.3);//初始化时进行赋值不能 a = 20;
      }

  • 拷贝构造函数

      Class A
      {
      ...
      A(const A& C)
      }
      
      构造函数的对象时该类的引用,用于
      A a(20),b;
      a=b;
    
    • 编译器的默认的拷贝构造函数的功能:给成员变量赋值,是浅拷贝

    • 会拷贝对象,但不拷贝静态成员

    • 浅拷贝对于动态量会出错(指针会对同一区域多次销毁导致错误)

    • 深拷贝对于动态量进行new操作

    • 用于复制对象产生新实例

    • 用引用传递时防止递归

    • 特殊的构造函数

    • 当类定义的同时赋值会不执行构造函数而执行拷贝函数

         	当 一个对象需要以值方式传递时,编译器会生成代码调用它的拷贝构造函数以生成一个复本。如果类A的拷贝构造函数是以值方式传递一个类A对象作为参数的话,当 需要调用类A的拷贝构造函数时,需要以值方式传进一个A的对象作为实参; 而以值方式传递需要调用类A的拷贝构造函数;结果就是调用类A的拷贝构造函数导 致又一次调用类A的拷贝构造函数,这就是一个无限递归。
      
    • 参数形式

       	a) X&
        b) const X&
        c) volatile X&
        d) const volatile X&
      
    • 类中可以存在超过一个拷贝构造函数

        注意,如果一个类中只存在一个参数为 X& 的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化.
        如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。
        这个默认的参数可能为 X::X(const X&)或 X::X(X&),由编译器根据上下文决定选择哪一个。
      
    • 必须重载运算符

    • 永远要显式拷贝构造函数或operate=或=default

  • 运算符重载

    • 不可重载的运算符:

        	.成员访问运算符 	
        	.*和->*成员指针运算符	
        	::域运算符		
        	sizeof长度运算符		
        	?:条件运算符	
        	#:预处理符号
      
    • 定义
      xx operatorx (。。。); xx为返回值,x为运算符
      运算符的优先级、结合性、操作数个数和语法结构保持不变

  • new

    • 失败时有些编译器(按C++标准)会抛出【bad_alioc】异常不返回空指针,有些不会抛出异常而返回空指针,【new (std::nothorw) int 】则可以把抛出异常转为空指针
    • set_new_handler(传入已经定义的错误处理函数) 来处理 在new之前设置

C++ 的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。 没有定义时系统会自动隐式定义

=default会把自动生成的特殊成员函数显式

在函数后加上 =delete 相当于private ,析构函数不能加

  • 析构函数

    • 一般定义为虚函数

    • 类销毁时调用
      class A{~A()}

    • 固定delete[] 指针

  • 友元

      在类中对某个方法定义前加friend ,在类外定义可以使用该函数的私有,在使用其非静态变量时需用其对象
    
  • 参数加const

      表示常量,使this指针变为常指针常量
    
  • 构造函数

    • 基类有有参时,派生类必须对其初始化
    • 定义为全局的对象的构造函数先于main执行

=default

结构体

  • “:”位域,规定数据占的比特数

      struct A{
      int b:2;
      int :3;  /
      int c:3}
    

多态

动态绑定

  • “指针->函数()”或“引用变量.函数()”的方式调用C++类中的虚函数才会执行

编译和运行的不同

  • virtual

    • 虚函数

        不一定被子类重写
        在类中会产生4个字节存放虚函数表的地址
      
    • 纯虚函数
      纯虚函数的语法:将成员函数定义为virtual后面加上 = 0该函数没有函数体,调用时使用指针,即抽象函数,必须被子类重写
      virtual <类型><函数名>(<参数表>) = 0;
      有纯虚函数的类为接口(或抽象类)

    • 虚基类

        :virtual public A;
        继承的多个类的共同的父类,该父类只有一个对象;		
      
  • inline 内联函数

    • 不能包含循环函数!

      编译时在使用的地方插入函数的代码,用于不复杂但使用频繁的函数

    • 函数多语句用内联,单语句用define(可能)

switch
- 在4个以上时效率高于if,4个以下差不多

数据结构

  • 10种排序

  • 队列

    • 循环队列
  • 内模式

      多个属性构成的一个实体的形式
      内模式时最底层的,给出类数据库物理存储结构和存取方法
    

模板

其他

pragama pack(n)

	设置对齐