C++笔记上

目录
  • 类型转换
  • 自定义类型
    • 类型别名:为已有的类型另外命名
    • 枚举类型
    • auto类型
    • decltype类型
  • 函数的参数传递
  • 含有可变个数参数的函数
  • 内联函数
  • 带默认参数值的函数
  • 函数重载
  • 类与对象
  • 类和对象的定义
  • 构造函数
  • 委托构造函数
  • 复制构造函数
  • 析构函数
  • 类的组合
  • 前向引用声明
  • 结构体
  • 联合体
  • 枚举类
  • 数据的共享与保护
    • 标识符的作用域和可见性
    • 对象的生存期、
    • 类的静态数据成员
    • 类的友元
    • 共享数据的保护
    • 多文件结构和编译预处理命令
  • 数组
    • 数组的定义与使用
    • 数组的存储和初始化
    • 对象数组
    • 基于范围的FOR循环
  • 指针
    • 指针的概念、定义和指针运算
    • 指针的初始化和赋值
    • 指针的算术运算、关系运算

类型转换


  • 显式类型转换
    • 语法形式:
      • 类型说明符(表达式)
      • (类型说明符)表达式
      • 类型转换操作符<类型说明符>(表达式)
        • const_cast dynamic_cast reinterpret_cast static_cast(用的多)
  • 例子(等价写法)
int(z);
(int)z;
static_cast(z);

自定义类型

类型别名:为已有的类型另外命名

  • 使用typedef

    • typedef 已有类型名 新类型名表
    typedef double Area, Volume;
    typedef int Natural;
    Natural i1,i2;
    Area a;
    Volume v;
    
  • 使用using

    • using 新类型名 = 已有类型名
    using Area = double;
    using Volume = double;
    

枚举类型

  • 语法形式:enum 枚举类型名 {变量值列表}
    • 默认情况下:SUM=0,MON=1,TUE=2,......,SAT=6
    enum Weekday {SUM,MON,TUE,WED,THU,FRI,SAT};
    
  • 枚举元素是常量,不能对他们赋值,如:SUM=0;
  • 定义时,给枚举元素指定不同值:
enum Weekday{SUN=7,MON=1,TUE,WED,THU,FRI,SAT};
  • 整数不能直接赋值给枚举变量,需要时,使用强制类型转换
#include 
using namespace std;
//定义枚举类型
enum GameResult {WIN,LOSE,TIE,CANCEL};
int main() {
    //定义该枚举类型变量,两种方式,可以带enum或者不带
    GameResult result;
    enum GameResult omit = CANCEL;
    for(int count = WIN; count <= CANCEL; count++){
        result = GameResult(count);
    }
        
}
  • 枚举值可以赋值给int,但是int类型不能直接赋值给枚举类型变量

auto类型

  • auto:编译器通过自动推断变量类型
  • 例如:auto val = val1 + val2;

decltype类型

  • 定义一个变量与某一表达式类型相同
  • 例如:decltype(i) j=2;
  • 表示j以2作为初始值,类型与i一致

函数的参数传递

  • 函数被调用时才分配形参的存储单元
  • 实参类型必须与形参相符,否则编译器会进行隐含类型转换
  • 值传递是传递参数值,即单向传递
  • 引用可以实现双向传递
  • 常引用用于保护实参安全(即使得实参不被改变)
    • 引用开销小,且有时候不希望双向传递
  • 引用类型:定义引用时必须初始化,使他指向一个已存在的对象
int i,j;
//定义int引用ri,并初始化为变量i的引用
int &ri = i;

含有可变个数参数的函数

  • 如果所有实参类型相同,可以传递名为initializer_list的标准类型
  • 如果实参类型不同,需要编写可变参数的模板

内联函数

  • 调用简单函数时,能提高运行效率的机制,不需要经过转子函数返回这样的要花费开销的过程
  • 通过编译器实现的,实际上是编译时使用函数体中语句,替换函数调用表达式
  • 内联函数声明时使用关键字inline,这是对编译器的一个建议(不一定最终采纳)
#include 
using namespace std;

const double PI=3.1415926;
inline double calArea(double radius){
    return PI*radius*radius;
}
int main(){
    double r = 3.0;
    double area = calArea(r);
    cout << area << endl;
    return 0;
}

带默认参数值的函数

  • 预先设置默认参数值,调用时给出实参则采用,否则采用预先设置的默认参数值
int add(int x=5, int y=6){
    return x+y;
}
int main(){
    add(10,20);//10+20
    add(10);//10+6
    add();//5+6
}
  • 默认参数的形参必须在形参列表的最右端
  • 调用时实参与形参结合顺序时从左向右

函数重载

  • 由静态多态性实现,在编译阶段实现
  • 函数重载:允许功能相近参数类型不同、参数个数不同、顺序不同的函数使用相同函数名
int sumofsquare(int a, int b){
    return a*a+b*b;
}
double sumofsquare(double a,double b){
    return a*a+b*b;
}
int main(){
    int m,n;
    cin >> m >> n;
    cout << sumofsquare(m,n) << endl;//调用第一个,根据参数类型
    double x,y;
    cin >> x >> y;
    cout << sumofsquare(x,y) << endl;
    return 0;
}

类与对象

  • 对象:现实中对象的模拟,具有属性和行为。
  • 类:同一类对象的共同属性和行为。
  • 定义对象时,通过构造函数初始化。
  • 删除对象时,通过析构函数释放资源。
  • 面向对象基本特点抽象、封装、继承、多态

类和对象的定义

  • 类定义的语法形式
    • 公有成员:任何外部函数都可以访问公有类型数据和函数
    • 私有成员:只允许本类中的函数访问,而外部任何函数不能访问
    • 保护成员:与私有成员很想,在继承和派生时不同
class 类名称
{
    public:
        公有成员(外部接口)
    private:
        私有成员
    protected:
        保护型成员
};
  • 类内初始值
class Clock{
    public:
        void setTime(int newh, int newm, int news);
    private:
        //类内初始值
        int hour = 0, minute = 0, second = 0;
};
  • 对象定义语句
Clock myClock;
  • 类的成员访问:
    • 类中成员访问直接使用成员名
    • 从类外访问成员使用“对象名.成员名”方式访问public成员
  • 类的成员函数
    • 在类中声明函数原型
    • 可以在类外给出函数体实现,并在函数名前使用类名加以限定
    • 也可以直接在类中给出函数体,形成内联成员函数
      • 内联成员函数:1 将函数体放在类的沈明中,2 使用inline关键字
    
    
    • 允许声明重载函数和带默认参数值的函数
  • 类的定义和对象的使用
#include
using namespace std;

class Clock{
    public:
        void setTime(int newh=0, int newm=0, int news=0);
        void showTime();
    private:
        int hour, minute, second;
}

void Clock::setTime(int newh=0, int newm=0, int news=0){
    hour = newh;
    minute = newm;
    second = news;
}

void Clock::showTime(){
    cout << hour << ":" << minute << ":" << second;
}

int main(){
    Clock myClock;
    myClock.setTime(8,30,30);
    myClock.showTime();
    return 0;
}

构造函数

  • 类中用于描述初始化算法的函数,在对象被创建时使用特定值构造对象
  • 构造函数的形式:
    • 函数名与类名相同
    • 不能定义返回值
    • 可以有形参也可没有形参
    • 可以是内联函数
    • 可以重载
    • 可以带默认值
  • 构造函数在对象被创建时自动调用
  • 如果程序中已经定义构造函数,默认情况下编译器就不再隐含生成默认构造函数。如果依然希望编译器隐含生成默认构造函数,可以使用“类名() = default”,如:“Clock() = default”
class Clock{
    public:
        //构造函数
        Clock() = default;
        Clock(int newh, int newm, int news);
    private:
        int hour, minute, second;
};

//构造函数的实现
//下列是初始化列表方式初始化
Clock::Clock(int newh, int newm, int news):hour(newh),minute(newm),second(news){}

//自动调用构造函数
int main(){
    Clock c1(8,10,0);//调用有参数的构造函数
    Clock c2;//调用无参数的构造函数
    return 0;
}

委托构造函数

  • 委托另一个构造函数初始化成员
  • 以下情况使用委托构造函数
Clock::Clock(int newh, int newm, int news):hour(mewh),minute(newm),second(news){}
Clock::Clock():hour(0),minute(0),second(0){}
//上述写法委托构造函数的版本
Clock::Clock(int newh, int newm, int news):hour(mewh),minute(newm),second(news){}
Clock::Clock(0,0,0){}//无参数的构造函数调用有参数的构造函数,将默认的初始化参数传给由参数表的构造函数

复制构造函数

  • 复制构造函数规定:如何用已经存在的对象初始化新对象
  • 不定义时,编译器生成默认的复制构造函数(实现两个对象的每个数据成员间的一一复制)
  • 复制构造函数的定义:
    • 复制构造函数时一种特殊的构造函数,其形参是本类的对象引用。作用是用一个已存在的对象去初始化同类型的新对象
    class 类名{
        public:
            类名(形参);
            类名(const 类名 &对象名);//复制构造函数,const是为了保护实参不被修改
        //...
    };
    类名::类名(const 类名 &对象名){
        函数体
    }
    
  • 三种情况会调用复制构造函数:
    • 定义一个对象时,以另一对象作为初始值
    • 函数形参是类的对象,调用函数时,将使用实参对象初始化形参对象,此时发生复制构造
    • 如果函数返回值是类的对象,函数执行完成返回主调函数是,将使用return语句中的对象初始化一个临时的无名对象,传递给主调函数,此时发生复制构造
class Clock{
    public:
        //构造函数
        Clock() = default;
        Clock(int newh, int newm, int news);
        Clock(const Clock& p) = delete;//指示编译器不生成默认复制构造函数
    private:
        int hour, minute, second;
};

析构函数

  • 析构函数:对象生存期消亡时,所需要的一些清理工作(生存期结束时,析构函数会自动调用)
  • 如果不定义,编译器自动生成,此时函数体为空
  • 析构函数:
    ~类名()
  • 析构函数没有参数,没有返回类型
#include
using namespace std;

class Point{
    public:
        Point(int xx, int yy);
        ~Point();
        //其他函数原型
    private:
        int x,y;
};

Point::Point(int xx, int yy){
    x = xx;
    y = yy;
}

Point::~Point(){
}

//其他函数实现

类的组合

  • 组合的概念: 类中成员是另一个类的对象,可以在已有抽象的基础上实现更复杂的抽象
  • 类组合的构造函数设计:
    • 原则:不经负责对本类中的基本类型成员数据初始化,也要对对象成员初始化(不能直接访问对象的私有成员,通过调用对象的所属类的构造函数初始化对象成员)
    类名::类名(对象成员所需的形参,本类成员形参):对象1(参数),对象2(参数),......{
        //函数体的其他语句
    }
    
  • 构造组合类对象时的初始化次序
    • 首先对构造函数初始化列表中列出的成员(包括基本类型成员和对象成员)进行初始化,初始化次序是成员在类体中定义的次序
      • 初始化列表中未出现的成员对象,调用默认构造函数初始化
    • 处理完初始化列表之后,再执行构造函数的函数体

前向引用声明

  • 类应先声明后使用
  • 如果需要在某个类的声明之前,引用该类,则应该进行前向引用声明
  • 前向引用声明只为程序引入标识符
class B;
class A {
    public:
        void f(B b);
};
class B {
    public:
        void g(A a);
};
  • 注意事项
    • 在提供完整的类声明之前,不能声明该类的对象,也不能在内敛成员中使用该类对象
    • 即:当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何细节
    class Fred;
    class Barney {
        Fred x;//要声明对象起码要知道字节数,而此时不知道细节,发生错误
    };
    class Fred {
        Barney y;
    };
    

结构体

  • 结构体是一种特殊形态的类
  • 与类的唯一区别
    • 类的缺省访问权限是private
    • 结构体的缺省访问权限是public
  • 什么时候使用结构体而不用类
    • 定义主要用来保存数据,而没有什么操作的类型
    • 人们习惯将结构体的数据成员设置为公有,因此这时用结构体方便
  • 结构体的的定义
struct 结构体名称 {
        公有成员;
    protected:
        保护型成员;
    private:
        私有成员;
};
  • 结构体中可以有数据成员和函数成员
  • 结构体初始化
    • 如果结构体的全部数据成员都是公共成员
    • 没有用户定义的构造函数
    • 没有基类和虚函数
    • 那么可以用下面语法初始化
    类型名 变量名 = {成员数据1初始值,成员数据2初始值,......};
    
#include 
#include 
#include 
using namespace std;

struct Strudent {
    int num;
    string name;
    char sex;
    int age;
};

int main(){
    Student stu = { 97001, "Lin Lin", "F", 19};
    cout << "Num: " << stu.num << endl;
    cout << "Name: " << stu.name << endl;
    cout << "Sex: " << stu.sex << endl;
    cout << "Age: " << stu.age << endl;
    return 0;
}

联合体

  • 与类,结构体很像,但是联合体的目的是存储空间的共用
  • 联合体的成员不是同时存在,同时起作用的,他们必须不同时存在
  • 定义形式:
//下面这些成员不是同时存在,同时起作用的,他们必须不同时存在
union 联合体名称 {
    公有成员
    protected:
    保护型成员
    private:
    私有成员
};
  • 特点:
    • 成员共用同一组内存单元,空间安装成员中最大分配
    • 任何两个成员不同时有效
  • 举例说明:
union Mark {
    char grade;//等级制成绩
    bool pass;//是否通过
    int percent;//百分制
}
  • 无名联合体
union {
    int i;
    float f;
};
//在程序中这样使用
i = 10;
f = 2.2;

枚举类

  • 强类型枚举
  • 枚举类定义
    • 语法形式
      enum class 枚举类型名:底层类型{枚举值列表}
  • 例:
enum class Type{General, Light, Medium, Heavy};//默认为int类型
enum class Type:char{General, Light, Medium, Heavy};//这些枚举常量是字符型的
enum class Gategory{General=1, Pistol, MachineGun, Cannon};
  • 枚举类相对简单枚举类型优势
    • 强作用域:枚举值作用域限制在枚举类中
    //使用Type的枚举值General:
    Type::General
    
    • 转换限制:枚举类对象不能和整明隐式地相互转换
    • 可以指定底层类型
enum class Side{Right,Left};
enum class Ting{Wring,Right};
int main(){
    Side s = Side::Right;
    Ting w = Thing::Wrong;
    cout << (s == w) << endl;
    return 0;
}
  • 实验一:构造函数,析构函数
#include
using namespace std;

enum CPU_Rank {P1=1,P2,P3,P4,P5,P6,P7
};
class CPU{
    public:
        CPU(CPU_Rank r, int f, float v){
            rank = r;
            fraquency = f;
            voltage = v;
            cout << "构造了一个CPU" << endl;
        }
        ~CPU(){
            cout << "析构了一个CPU" << endl;
        }
        void run(){cout << "CPU开始运行" << endl;}
        void stop(){cout << "CPU停止运行" << endl;}
    private:
        CPU_Rank rank; 
        int fraquency;
        float voltage;
}

int main(){
    CPU a(P6,300,2.8);
    a.run();
    a.stop();
    return 0;
}
  • 实验二:类的组合
class COMPUTER{
    private:
        CPU my_cpu;
        unsigned int storage_size;
        unsigned int bandwidth;
    public:
        COMPUTER(CPU c, unsigned int s, unsigned int b){
            my_cpu = c;
            storage_size = s;
            bandwidth = b;
            cout << "构造函数" << endl;
        }
        ~COMPUTER() {
            cout << "析构函数" << endl;
        }
        void run(){
            my_cpu.run();
            cout << "computer 开始运行" << endl;
        }
        void stop(){
            my_cpu.stop();
            cout << "computer停止运行" << endl;
        }
}
int main() {
    CPU a(CPU_Rank::P6, 300, 2.8);
    a.run();
    a.stop();
    cout << "*********" << endl;
    COMPUTER my_computer(a, 100, 1000);
    cout << "********" << endl;
    my_computer.run();
    my_computer.stop();
    return 0;
}

数据的共享与保护

  • 变量和对象的作用域、可见性、生存期
  • 属于整个类的数据成员————静态数据成员
  • 用于处理静态数据成员的函数————静态函数成员
  • 友元:对一些类外的函数、其他类,给予预授权,使之可以访问私有成员
  • 通过const关键字,限制对共享数据的修改

标识符的作用域和可见性

  • 作用域分类:
    • 函数原型作用域
    • 局部作用域(块作用域)
    • 类作用域
    • 文件作用域
    • 命名空间作用域
  • 函数原型作用域(即声明时的参数作用域):
    • 函数原型中的参数
    • 作用域起始于函数形参表的左括号“(”,结束于右括号“)”
    double area(double radius);
    
  • 局部作用域
    • 一般用大括号限定块
    • 函数的形参,在块中声明的标识符具有局部作用域
    • 作用域自声明处起,限于块中
      C++笔记上_第1张图片
  • 类作用域
    • 类的成员具有类作用域
      *其范围包括类体和成员函数体
    • 在类作用域以外访问类的成员
      • 静态成员:通过类名,或者该类对象名、对象引用访问
      • 非静态成员:通过类名,类对象名、对象引用、对象指针访问
  • 文件作用域
    • 不在前述各个作用域中出现的声明,就具有文件作用域
    • 其作用域起始于声明点,结束于文件尾

  • 可见性
    • 即使在作用域内,也要是具有可见性,只有具有可见性,才能够访问
    • 可见性时从对标识符的引用角度来谈的概念
    • 可见性表示从内层作用域向外层作用域看时,能看见什么
    • 如果标识符在某处可见,就可以在该处引用此标识符

C++笔记上_第2张图片

  • 例子:
    C++笔记上_第3张图片

对象的生存期、

  • 含义:对象产生到结束期间就是他的生存期
  • 静态生存期(静态不是指对象不可变):
    • 这种生存期与程序运行期间相同
    • 在文件作用域中声明的对象具有这种生存期
    • 在函数内部声明静态生存期对象,要冠以关键字static
    • 第二次进入不在初始化
  • 动态生存期
    • 开始于声明点,结束于命名该标识符的作用域结束处
    • 块作用域中声明的,没有用static修饰的对象是动态生存期对象(习惯称作局部生存期对象)
    • 第二次进入该区域会重新初始化
  • 例子
    C++笔记上_第4张图片
    C++笔记上_第5张图片
    image.png

类的静态数据成员

  • 用关键字static声明
  • 为该类的所有对象共享,静态数据成员具有静态生存期
  • 声明在类体里面,但必须在类外定义和初始化,用(::)来指明所属的类
  • 因为静态数据成员是属于类的,所以用“::”来指明所属的类
#include
using namespace std;

class Point{
    public:
        Point(int x=0,int y=0):x(x),y(y){
            count++;
        }
        Point(Point &p){
            x = p.x;
            y = p.y;
            count++;
        }
        ~Point(){
            count--;
        }
        int getx(){
            return x;
        }
        int gety(){
            return y;
        }
        void showcount(){
            cout << "count = " << count << endl;
        }
    private:
        int x,y;
        static int count;
};
int Point::count = 0;

int main(){
    Point a(4,5);
    cout << "Point a: " << a.getx() << "," << a.gety() << endl;
    a.showcount();
    
    Point b(a);
    cout << "Point b: " << b.getx() << "," << b.gety() << endl;
    b.showcount();
    return 0;
}
  • 关键字static的作用:使对象或对象具有全局的寿命,当程序第二次访问同一个块时,不需要重新初始化,直接引用当前值
    • static上述特性,刚好用于定义静态数据成员,使得该类下的所有对象共享同一个值。

类的友元

  • 类的友元使得属于该类友元的类或函数可以访问该类的私有成员
  • 友元使C++提供的一种破坏数据封装和数据隐藏的机制
  • 通过将一个模块声明为另一个模块的友元,一个模块可以引用另一个模块本被隐藏的信息
  • 可以声明友元函数,和友元类

  • 友元函数
    • 友元函数使在类声明中由关键字friend修饰说明的非成员函数,在他的函数体中能通过对象名访问private和protected成员
    • 作用:增加灵活性
    • 访问对象中的成员必须通过对象名
#include
#include
using namespace std;
class Point {
public:
    Point(int x = 0, int y = 0) :x(x), y(y) {}
    int getx() { return x; }
    int gety() { return y; }
    friend double dist(const Point& a, const Point& b);
private:
    int x, y;
};

double dist(const Point& a, const Point& b) {
    double x = a.x - b.x;
    double y = a.y - b.y;
    return (sqrt(x * x + y * y));
}

int main() {
    Point p1(1, 1), p2(2,2);
    cout << "the distance is: " << dist(p1, p2) << endl;
    return 0;
}

  • 友元类
    • 若一个类为另一个类的友元,则此类的所有成员都可以访问对方类的私有成员
    • 声明语法:将友元类名在另一个类中使用friend修饰说明
class A{
    friend class B;
    Public:
        void display(){
            cout << x << endl;
        }
    private: 
        int x;
};

//B的成员是另一个类对象,所以是组合类
class B{
    public:
        void set(int i);
        void display();
    private:
        A a;
};

void B::set(int i){
    a.x=i;//连A类对象自己都不能直接访问Private成员x;
}

void B::display(){
    a.display();
}

int main(){
    A a;
    B b;
    b.set(11);
    b.display();
    return 0;
}

  • 类的友元关系是单向的

共享数据的保护

  • 如果既要共享数据,又想保证数据安全性(不被修改),就需要将数据定义为常类型,即用const修饰

  • 常类型
    • 常对象:必须初始化,不能被更新
      const 类名 对象名;
    • 常成员:用const修饰的类成员,有常数据成员和常函数成员
    • 常引用:被引用的对象不能被更新,即只读的引用
      const 类型说明符 &引用名
    • 常数组
    • 常指针

  • 常成员
    • 常成员函数指得是:该函数不改变对象状态,const修饰的应该是大括号
      • 常成员函数原型:
        类型说明符 函数名(参数表) const;
        C++笔记上_第6张图片
    • 常数据成员:只能在初始化列表中初始化,不能在函数体中赋值

多文件结构和编译预处理命令

  • C++文件的一般组织结构
    • 类声明文件(.h文件)
    • 类实现文件(.cpp文件)
    • 类的使用文件(main()所在的.cpp文件)
      C++笔记上_第7张图片
      C++笔记上_第8张图片
      C++笔记上_第9张图片
      C++笔记上_第10张图片

  • 外部变量
    • 除了在定义它的源文件中可以使用外,还能被其他文件使用
    • 文件作用域(全局作用域)下定义的变量,默认为外部变量
    • 在其他文件中如果需要使用,需要用extern关键字声明
  • 外部函数
    • 在所有类之外声明的函数,都是具有文件作用域的
    • 这样的函数可以在不同编译单元被调用
    • 只要在调用之前进行引用性声即可(即声明函数原型)

  • 只有全局变量才能被其他文件中的extern引用到:
    • 这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说main.c要引用到value,不只是取决于在main.c中声明extern int value,还取决于变量value本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。
  • extern声明的变量的作用域取决于声明位置:
    • 还有很重要的一点是,extern int value可以放在main.c中的任何地方,比如你可以在main.c中的函数fun定义的开头处声明extern int value,然后就可以引用到变量value了,只不过这样只能在函数fun作用域中引用value罢了,这还是变量作用域的问题。

  • 有时并不希望当前文件中定义的标志符被拿到其他文件中使用
    image.png

  • 编译预处理
    C++笔记上_第11张图片

    C++笔记上_第12张图片
    C++笔记上_第13张图片
    image.png
    C++笔记上_第14张图片

数组

数组的定义与使用

  • 数组是具有顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素
  • 数组的定义
    类型说明符 数组名[常量表达式][常量表达式]......;
  • 数组元素的使用
    • 数组需要先定义后使用
    • 可以逐个引用数组

数组的存储和初始化

  • 一维数组的存储
    • 数组元素在内存中顺序存放,他们的地址是连续的
    • 数组名字是数组的首元素的内存地址
    • 数组名是一个常量,不能被赋值
  • 一维数组的初始化
    • 列出全部元素的初始值
      static int a[10]={0,1,2,3,4,5,6,7,8,9};
    • 给一部分元素指定初值
      static int a[10]={0,1,2,3,4};
    • 列出全部元素时,可以不指定数组长度
      static int a[]={0,1,2,3,4,5,6,7,8,9};
  • 二维数组的存储
    • 是一维数组的数组
  • 二维数组的初始化
    • 将所有处置写在一个{}内,按顺序初始化
      static int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
    • 分别列出二维数组元素处置
      static int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
    • 只对部分元素初始化
      static int a[3][4]={{1},{5,6,},{9,10,11}};
    • i而出全部初始值时,一维下标个数可以省略
      static int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12};
  • 初始化问题
    • 如果不做任何初始化,局部作用域的非静态数组中会存在垃圾数据,static数组中数据会默认初始化为0
    • 如果部分初始化,剩余部分默认初始化为零

对象数组

  • 对象数组的定义与访问
    • 定义对象数组:类名 数组名[元素个数]
    • 访问对象数组元素:数组名[下标].成员名
  • 对象数组的初始化
    • 数组中每个元素被创建时,系统会调用类构造函数初始化对象
    • 通过初始化列表赋值:Point a[2] = {Point(1,2),Point(3,4)};
    • 如果没有为数组指定显式的初始值,数组元素使用默认值初始化

基于范围的FOR循环

  • 处理容器类的基于范围的FOR循环:能够自动依次处理容器中的全部数据
#include
int main(){
    int array[3] = {1,2,3};
    for(int &e : array){
        e += 2;
        std::cout << e << std::endl;
    }
    return 0;
}

指针

指针的概念、定义和指针运算

  • 内存空间的访问方式
    • 通过变量名访问
    • 通过地址访问
  • 指针的概念
    • 指针:内存地址,用于访问内存单元
    • 指针变量:用于存放地的址变量
  • 指针变量的定义和访问
static int i;
static int* ptr = &i;//“&”取址运算符
*ptr = 3;//通过指针访问变量

image.png

指针的初始化和赋值

  • 指针变量的初始化:
    存储类型 数据类型 *指针名=初始地址;
    C++笔记上_第15张图片
  • 不能用内部非静态变量初始化static指针
  • 指针变量的赋值
    • 语法形式:指针名=地址;
    • “地址”中存放的数据类型必须与指针类型相符,向指针变量赋的值必须是地址常量或者变量,不能是普通整数
      C++笔记上_第16张图片

  • 指向常量的指针
    • const指针(只授权指针读的权限)
    • 不能通过指向常量的指针改变所指对象的值,但指针本身可以改变,可以指向另外对象
      C++笔记上_第17张图片
  • 指针常量
    • 指针常量:指针本身是常量,指针的值不能改变
    int a,b;
    int * const p2 = &a;
    p2 = &b;//错误,p2是指针常量,不能改变
    

指针的算术运算、关系运算

  • 算数运算
    C++笔记上_第18张图片
  • 关系运算
    • 指针只能和 相同类型指针之间进行关系运算
    • 指针可以和零进行关系运算
    p==0;
    p!=0;
    

你可能感兴趣的:(C++笔记上)