typedef

typedef并不是简单的宏替代。

  • 定义一种类型的别名
  • 定义struct结构体别名
  • 用typedef来定义与平台无关的类型
  • 复杂的声明定义一个简单的别名,表示的是一个指向函数的指针
  • typedef可以定义各种类型别名,但不能定义变量
  • 使用typedef便于程序的通用
  • typedef只是将一个已经存在的类型用一个新的名称替代
  • typedef不能添加新类型

typedef#define区别

typedef 是一种类型别名,而#define只是宏定义,二者并不总是可以互换的。

比较函数

C++的比较函数适用于整型字符串浮点数等多种类型。

max

返回队列中的最大值,参数两个参数,如果想要多个参数,使用大括号初始化列表容器的形式可以,但相比于直接两个两个比较比较耗时

#include <iostream>
#include <algorithm>
using namespace std;
int main(void)
{
	float a = 1.359;
	float b = 1.823;
	float c = 1.829;
	auto result = max({ a, b,c });
	cout << result << endl;
	return 0;
}

min

返回队列中的最小值

minmax

算法标头的库函数,用于查找最小和最大值,它接受两个值并返回一对最小和最大值,该对中的第一个元素包含最小值,并且该对中的第二个元素包含最大值

该函数包括<algorithm>头文件,

#include <iostream>
#include <algorithm>
using namespace std;
int main(void)
{
    //字符串类型同样应用于比较,会以ASCII码值进行对比
	int a = -10;
	int b = -20;
	auto result = minmax(a, b);
	cout << "最小值" << result.first << endl;
	cout << "最大值" << result.second << endl;
	return 0;
}

友元

在函数前加 friend

友元成员函数,但是它可以访问类中私有保护成员。

提高了程序的运行效率,但是破坏了类的封装和隐藏,使得非成员函数可以访问类的私有成员。

  • 友元具有不对称性,即A是B的友元,但B不一定是A的友元,单向的,不具有交换性

  • 友元关系不具传递性

  • 友元关系不能被继承

main参数

main函数有三个参数,argcargvenvp

int main(int argc,char*argv[],char*envp[])
{
    
}
// **int argc:存放了命令行参数的个数
// char argv[] 是个字符串的数组,每个元素都是一个字符指针,指向一个字符串,即命令行中的每一个参数
// char envp[] 也是一个字符串的数组,这个数组的每一个㢝是指向一个环境变量的字符指针

(图片 image-20230716092743942.png 未随仓库迁移,原引用路径已失效)

  • floatdoublelong double等类型不允许直接进行位与操作符

  • float取地址(也是符号)转换为unsigned int 类型,再用取值操作符(*),编译器会识别为unsigned int类型

  • 使用int short long移位时,最好加上unsigned,这样就是汇编中规律移位(即全部移位)

  • 加入不加unsigned,正数全是规律 移位,负数左移保持符号位为1,右边补0,负数右移时保持符号位为1左边补1,所有-1无论怎么右移都是-1

  • 位与操作符的操作优先级小于 移位操作符,但移位操作符小于取地址操作符(取值操作符*·*)

static

静态数据成员类内定义,就必须在类外初始化

特点:

  • 所有成员都共享数据成员,只有一份内存
  • 必须在类外进行初始化

静态数据成员的内存?

存放在内存的全局区

内存分配

基类的静态数据成员不能被继承

  • 继承:继承是一个类另一个类获取成员变量成员函数的过程(子类继承父类)

基类继承
基类继承

继承特性:

  • 继承访问父类私有属性
  • 但是有继承已经被继承,被编译器隐藏
  • 静态成员属性不会被继承(属于全部对象)
  • 创建子类时,构造函数的调用,先父类后子类析构时:先子类后父类
  • 构造函数析构函数赋值操作符不能被继承

无论什么继承,子类可以访问基类中公共保护成员,但子类对象就只能访问子类的公共成员

在析构时:

  • 释放子类的指针对象时,会调用子类和父类的析构函数
  • 当释放子类的指针对象时,只会调用父类的析构函数
#include <iostream>
using namespace std;

class person//父类
{
public:
	person() { cout << "person的构造函数" << endl; }
	~person() { cout << "person析构函数" << endl; }
};
class son :public person
{
public:
	son() { cout << "son的构造函数" << endl; }
	~son() { cout << "son的析构函数" << endl; }
};
int main()
{
	son* s = new son;//定义一个子类指针
	person* p = s;//父类指针指向子类
	//delete s;//释放子类内存 //会调用子类和父类的析构函数
	delete p;  //释放父类 只会调用父类的析构函数
	return 0;
}

据成员什么必须类外初始化

静态数据成员也属于静态变量,属于静态全局区,全局区的变量,随着程序生死。而对象不是全局静态区的,是有生命周期的。由于生命周期的不同,所以必须在类外初始化,来解决类的生命周期问题。

  • static加强了访问控制全局变量继承
  • 类和子类对象,static变量占有一份内存

结构体内存

结构体内存规则

  • 第一个成员在与结构体变量偏移量为0地址处
  • 其他成员变量要对齐到对齐数的整数倍地址处
  • 对齐数 = min (编译器默认的对齐数,该成员大小)
  • 结构体总大小最大对齐数(每个成员变量都有一个对齐数)的整数倍
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己大的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数(函嵌套结构体的对齐数)的整数倍

C语言

变量类型

  • register:建议编译器将该变量放入CPU

函数类型缺省

  • 返回值
    • C语言,如果函数未指定返回值类型,则·默认int
    • C++ 如果函数没有返回值,默认类型必须指定为void
  • 参数列表
    • C语言,如果函数没有指定参数列表,返回值类型必须指定为void
    • C++中,有严格的类型检测,没有参数列表的函数默认为void,接受任意参数
  • 缺省参数
    • C不支持
    • C++支持,如果没有指定实参则使用缺省值,有则使用指定实参
      • 默认实参必须在参数列表的结尾
      • 默认参数只能出现在函数声明或者定义二选一中
      • 缺省值必须常量或全局变量
      • 缺省参数必须是值传递或者常参传递
  • 函数重载
    • C: 不支持
    • C++:支持

转义字符

  • \t表示横向指标
  • \v 表示竖向制表
  • \b 表示退格
  • \r 表示回车
  • \f 表示换页
  • \? 表示问号字符
  • \0 表示空字符(null)

指针大小

  • 指针,在64bit的机器中是8字节int 4字节

读取

  • getchar: 读取一个字符
  • %2d : 读取数字限定两个字符,如读取的指针位置后面出现字母忽略掉前面出现字母将全部忽略,指针移动到读取截止为止。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
    char c1, c2;
    int a1, a2;
    c1 = getchar(); //读取第一个字符 1
    scanf("%2d", &a1);  //读取宽度为两个,int型,只读取2
    c2 = getchar();  //读取a
    scanf("%3d", &a2);  //宽度为3,读物345
    printf("%d,%d,%c,%c\n", a1, a2, c1, c2);
    return 0;
}
/*
输入: 12a345b789
输出: 2,345,1,a
*/

优先级

成员选择符 -> 的优先级比前置++,和后置++都要

C语言运算符优先级
C语言运算优先级

字符串未赋值部分

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
    int a[3][3] = { {1,2},{3,4},{5,6} }, i, j, s = 0; //最后一个没有赋值的为0
    for (i = 1; i < 3; i++)
    {
        for (j = 0; j <= i; j++)
        {
            s += a[i][j];  //a[2][2] = 0
        }
    }
    printf("%d\n", s++);
    return 0;
}
/*
输出: 18
*/

表达式等级类型

基本类型字符串从低到高如下,运算的时候,从低转到高,表达式的类型自动提升为参与表达式求值最上级类

  • char
  • int
  • long
  • float
  • double

字符串操作

字符串时字符数组的一种形式,它以”\0”结尾

  • strcpy() : 复制字符串
  • strcmp() : 比较字符串
  • strlen() : 计算字符串的长度,遇到\0时结束计算不算\0,且从1开始计数。
// 将字符串source拷贝到字符串destination中
// 函数返回destination字符串
strcpy(char destination[], const char source[]);

// 将字符串source中前numchars个字符拷贝到字符串destination中
// 注意source中numchars个字符将覆盖掉字符串destination中前numchars个字符
// 函数返回destination
strncpy(char destination[], const char source[], int numchars);

// 将字符串source接到字符串target的后面,要提前确保taeget有足够的空间
// 函数返回target
strcat(char target[], const char source[]);
// 将字符串source的前nnumchars个字符接到字符串target的后面
strncat(char target[], const char source[], int numchars);

//比较 first是否大于second,成功大于0,
int strcmp(const char firststring[], const char secondstring);

// 统计长度
// 统计字符串string中字符的个数
strlen( const char string[]);

参考资料