上午
高级引用:
1.考察工作经验
1.1函数指针作为函数参数返回值
1.2函数指针的引用作为函数参数返回值
int(*z(int x, int (*y)(int))(int)
//一个参数是int ,一个参数是函数指针
z(int x,int (*y)(int))//函数调用,返回一个函数指针
int (*y)(int )=函数指针
函数指针 z(int x,函数指针)
更猥琐的面试题
int(*&z(int x,int (*&y)(int)))(int)
2.常用引用
Int a[10] int (&ra)[10]
Int a[2][5] int(&ra)[2][5];
int(&ra)[10](a)//引用就是给原来的变量有一个别名,指向同一地址
引用可以给您一个引用赋值
代码规范(c++初始化尽量用() 赋值就用=)
//引用一维数组
void main()
{
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int(&ra)[10](a);//引用一维数组//引用就是给原来的变量有一个别名,同一个地址
int i = 0;
for (auto data : ra)//c++11的循环
{
data = i + 5;
std::cout << data << std::endl;
}
std::cout << a << ra << std::endl;//输出a,ra的地址
std::cout << &a << std::endl;
system("pause");
}
引用2维数组
void main()
{
int a[2][5] = { 1, 2, 3, 4, 1, 3, 3, 9, 10 };
int(&ra)[2][5](a);//引用2维数组
for (auto data : ra)
{
for (int i = 0; i < 5; i++)
{
std::cout << " " << data[i];
}
}
system("pause");
}
函数指针引用
int(*& changep(int(*&rp)(int, int))) (int, int) //引用一个函数指针
{
rp = jian;
return rp;
}
int jia(int a, int b)
{
return a + b;
}
int jian(int a, int b)
{
return a - b;
}
void mai111111111n()
{
int(*p)(int, int)(jia);
std::cout << p(3, 4) << std::endl;
//int(*&rp)(int, int)(p);//引用一个函数指针
//rp = jian; //()仅仅适用于初始化
//change(p);
std::cout << p(3, 4);
system("pause");
}
void mainasdfas()
{
int(*p)(int, int)(jia);
std::cout << p(3, 4) << std::endl;
//int(*&rp)(int, int)(p);//引用一个函数指针
//rp = jian; //()仅仅适用于初始化
p = changep(p);
std::cout << p(3, 4);
system("pause");
}
引用数组(即每一个元素是引用)在c++中一定不合法
void main44()
{
//int *p[4];
int a = 1, b = 2, c = 3;
int*px[3] = { &a, &b, &c };
*px[1] = 3;
//int &px[3];不合法,引用数组
std::cout << b << std::endl;
system("pause");
//引用数组是非法的
}
关于C++中结构体内存对齐(以及引用的本质是指针,占4个字节)
struct mystruct
{
char a;
int b;
double c;//如果sizeof将是24个字节,结构体对齐
void go()
{
std::cout << "123456789" << std::endl;
}
};
class myclass
{
int a;
int b;
double h;//sizeof(myclass)16个字节
//如果是这样
/*int a
double h
int b sizeof将是24个字节
*/
};
class shuju
{
char &b;
char &c;
char &a;//占12个字节,因为引用是指针实现的 (引用本质是本身)直接sizeof引用就是求引用的数据大小
//引用变量占4个字节
};
void ma1111111111in()
{
int num = 10;
int &rnum(num);
double db = 10.9;
double &rdb(db);//rdb直接作用于引用的变量 占8个字节
std::cout << sizeof(myclass) << std::endl;
system("pause");
}
右值引用与左值引用
int getdata(int &&num) //引用右值 节约内存,如果不用右值引用,在内存再拷贝内存
//右值引用,那就在寄存器在保存在内存中
//右值引用,节约内存拷贝,内存优化所必须
{
std::cout << num << std::endl;
num += 10;
return num;//有副本机制
}
//左值,一般可以取地址就是左值
//右值某些情况可以,某些情况不可以
void mai1111111n()
{
int a = 4;
int b = 5;
std::cout << getdata(a+1) << std::endl; //a+1在寄存器中
system("pause");
}
void main32w3()
{
const int num(6);
char str[10]("hello ");
const char *pc(str);// 常量指针指向数组str //限定字符串不可以修改
str[3] = 'x';//可以改变
// pc[3] = 'y';错误因为pc是一个常量指针
pc = "asfla";//这个是可以的,改变了常量指针的指向
int a = 3;
int b = a + 1;//右值->左值
std::cout << getdata(std::move(a)) << std::endl;//std::move把左值转换为右值
}
void ma阿芳的飒飒in()
{
// int(*p)(int, int)(jia);
//int(*&rp)(int a, int b)(p);
char str[10]("hello ");
const char(&p)[10](str); //常量引用一个数组 +
const char(&rrstr )[10](p);//引用可以给拧一个引用初始化
//p[4] = 'y';错误 常饮用
}
void main()
{
int(*p)(int, int)(jia);
int(*const &rp)(int a, int b)(p);//常引用一个函数指针,无法修改函数指针指向
//rp = jian;错误,限定函数指针无法修改
}
2结构体
2.1结构体内部具备类的所有功能 .封装,继承,多态
2.2c++结构体内部可以有函数,C语言不可以
特点 1.代码区的函数不计入结构体的sizeof
2.代码共享.数据独有
C++结构体定义,可有可无struct ,C必须有
This指向自己的的指针
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<stdlib.h>
struct bigdatacom
{
protected:
char dataa[100];
char datab[100];
public:
void init(const char *str1, const char *str2)
{ //这str1则输出const char *
std::cout << typeid(*this).name() << std::endl; //输出其类型,比如此处输出struct bigdatacom
strcpy(this->dataa, str1);
strcpy(this->datab, str2);
}
};
//继承
struct smalldatacom :public bigdatacom
{
void zz()
{
std::cout << this->dataa << this->datab << std::endl;
}
};
int main()
{
bigdatacom z; //c++结构体初始化对象可以不要struct
z.init("hello", "world");//调用内部函数
system("pause");
return 0;
}
C语言结构体对比
//C语言声明变量需要加struct
//C语言结构体内部不可以有函数
//C语言结构体没有共有,私有,继承
struct mystruct
{
int num1;
int num2;
//void com()函数无法在结构中
};
Const补充
指向常量的指针限定指向的数据无法修改 //pc[3]=’y’,这样是错误的
但指针可以指向其他地方
Cin cout
默认是键盘,显示器
C++把所有设备都当成文件处理
文件可以重定向,CGI网页重定向
占位参数c++编译器编译的宽泛,为了修改源代码
后面留下拓展,留下占位参数,只有类型,无变量名,C语言没有
关于register变量(c++编译器不太听话)
C++编译器做了优化,检查到地址,就不会把它放在寄存器
C++自动优化,寄存器只是一个建议
强类型
C语言可以没有返回值,默认为int
C++必须有返回值类型-强类型
C/C++对于左值右值得差别
1.C语言不可以转换
2.C++会默认将当前有实体的右值转换为左值
以下C语言不合法/C++合法
1.(a>b?a:b)=2;
2.(++a)++
3.(a=3)=4
全局变量
1.c++无定义与声明的区别(extern类型变量可以声明多次)
C语言有声明定义区别
通用处理模式C++11 函数模板
Auto num=pdb//通用传入接口处理任何类型的变量
Decltype(db), numA(10.9)//通用备份接口
#include<stdlib.h>
#include<iostream>
#include<cstdarg>
//T是通用数据类型
//函数模板,可变参数
//参数至少要一个是模板类型
template<typename NT>
NT sum(NT count,NT data1, ...)//通用累加 //
{
va_list arg_ptr;//参数列表指针
va_start(arg_ptr, count);//限定从count开始,限定多少个参数
NT sumres(0);
for (int i = 0; i < count; i++)
{
sumres += va_arg(arg_ptr, NT);
}
va_end(arg_ptr);//结束
return sumres;
}
//T通用的数据类型//参数至少有一个是模板类型
template<typename T> T MAX(T*p, const int n)//通用数据类型 const避免恶意修改
{
T maxdata(p[0]);
for (int i = 1; i < n; i++)
{
if (maxdata < p[i])
{
maxdata = p[i];
}
}
return maxdata;
}
double getmax(double *p, double n)
{
int max(0);
max = p[0];//假定第一个数最大
for (int i = 1; i < n; i++)
{
if (max < p[i])
{
max = p[i];
}
}
return max;
}
int main11111111111()
{
double a[10] { 2, 3, 4, 98, 77 ,999,87,123,0,12};
int b[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << MAX(a, 10) << std::endl;
std::cout << MAX(b, 10) << std::endl;
system("pause");
return 0;
}
void mai11111111111n()
{
std::cout << sum(5, 1, 2, 3, 4, 10) << std::endl;
std::cout << sum(6.0, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1);
system("pause");
}
auto与函数模板
函数模板通用
T通用数据类型template<typename T>
可变参数的函数模板
//参数至少有一个是模板类型
#include<iostream>
#include<stdlib.h>
void main()
{
double db = 10.9;
double *pdb = &db;
auto num = pdb;//通用的传入接口
std::cout << typeid(db).name() << std::endl;//输出double *
std::cout << typeid(num).name() << std::endl;//输出double *
//typeid(db).name() numaa(10);错误,下面是对的
decltype(db) numA(10.8);//通用备份接口
std::cout << sizeof(numA) << std::endl;
system("pause");
}
自动数据类型,根据实际推导出类型
Template<class T1,class T2>//根据类型获取类型
Auto get(T1 data,T2 digdata>->decltype(data*bigdata)
//注意函数参数不可以使用自动变量
#include<stdlib.h>
#include<iostream>
/*
auto get(int num, double data)->decltype(num*data)
{
}
*/
//自动数据类型,根据实际推导出类型,auto是无法作为参数
template<class T1,class T2>//根据类型获取类型
auto get(T1 data, T2 bigdata)->decltype(data*bigdata)
{
return data*bigdata;
}
/*int putnum(auto num)
{
};*///函数参数不可以使用auto
void main()
{
std::cout << typeid(get(12.0, 'A')).name() << std::endl;//double
std::cout << typeid(get(12, 'A')).name() << std::endl; //int
std::cout << get(12, 'A') << std::endl;
system("pause");
}
Enum (c++强类型)
1.1Enum color :char(rea=’A’,yellow,green,white);
1.2避免类型直接转换造成程序错误
//新语法 mycolor =color::white
Color mycolor2(color::red)
C语言代码
#include<stdlib.h>
#include<stdio.h>
//C语言枚举
enum color{ red, yellow, green, white };
//
void mai阿斯顿发生发达n()
{
enum color color1;
color1 = red;
color1 = 11;//c语言弱类型,不注重数据类型
printf("%d", red);
printf("\n%d", yellow);
getchar();
}
C++代码
#include<iostream>
#include<stdlib.h>
enum color :char{red,yellow,green,white}; //char起到限定的作用,而且限定只能在4个中赋值
void main()
{
color mycolor = red;//
//mycolor = 1;错误,因为已经限定在char 1是int 赋值是错误的,确保在枚举的范围之内不出错
//mycolor='A';无法从char转换为color限定mycolor必须是其red,yellow,green,white
mycolor = color::white;//新语法
color mycolor1(red);
color mycolor2(color::red);
std::cout << red << std::endl;//输出编号为0的字符
system("pause");
}
Inlline(内联函数)
1.提升效率,对于C语言的define
2.类型会严格检查,类型安全
3.实现模板通用
Inline函数建议
1.一般情况下,我们对内联函数做了如下限制
2.不能有递归
3.不能包含静态数据
4.不能包含switch和goto
5.不能包含数组
6.若一个内联函数定义不满足以上限制,则编译系统吧他当作普通函数处理
内联函数会在函数内部展开
明确了内联函数,无法取地址
#include<stdlib.h>
#include<iostream>
/*
inline只是对于编译器的建议
一般情况下,我们队内联函数做了如下的限制
(1)不能有递归
(2)不能包含静态数据
(3)不能包括循环
4.不能包含swtich与goto语句
5.不能包含数组
//若一个内联函数定义不能满足以上限制,则编译器把他当做普通函数
*/
//替换
#define GETX3(N) N*N*N
//函数
inline int getX3(int x);//内联函数,内部展开
inline int getX3(int x) //类型安全
{
return x*x*x;
}
template<class T>
inline T getX2(T x)//c++类型如果不匹配会出错的,不是单纯的替换
{
return x*x;
}
int main()
{
std::cout << GETX3(1 + 2) << std::endl;
std::cout << GETX3((1 + 2)) << std::endl;
std::cout << GETX3((2.0 + 2)) << std::endl;
system("pause");
return 0;
}
New delete
全局重载
针对类的重载
New new[] delete delete[]区别
动态内存管理必须掌握
New 过程 局部new->全局new->malloc分配内存->构造
Delete过程 ->析构->局部delete->全局delete->free内存
New[]过程 ,局部new[]->局部new->全局new->malloc->free
Delete[]过程,->析构->局部delete[]->局部delete->全局delete->free释放内存
注意
1.数组一定要用delete[]
2.类的简单盖玲,构造与析构
3.指针分配在内存,往往指针在栈上,指针存储的地址是堆的地址
4.Delete以后尽量设置指针为空
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
void mai11111n()
{
int num=10;//在栈上
int *p = new int;
*p = 5;
std::cout << *p << " "<<p<<std::endl;//在堆上
delete (p);//删除后,将把p移到一个安全的地址 //只能释放一次
std::cout << p << std::endl;
system("pause");
}
void m111ain()
{
int *p = new int[10];//创建一个10*int 的内存大小空间
int i = 0;
for (int i = 0; i < 10;i++)
{
p[i] = i;//初始化,二维数组
std::cout << p[i] << std::endl;
}
delete[]p;//删除数组利用的空间
}
#include<iostream>
//调用构造函数与析构函数不意味着为类中的数据分配内存
class tansheng
{
public:
static int jisuqi;
int*p;
int length;//默认私有
public:
tansheng()//构建的时候初始化(构造函数)
{
std::cout << "tansheng被创建" << std::endl;
}
~tansheng() //删除的时候释放内存(析构函数)
{
std::cout << "tansheng被销毁" << std::endl;
}
static void *operator new(size_t size) //operator重载 //局部new调用构造函数没有分配内存,全局内才会分配内存
{ jisuqi++;
std::cout << "对象被创建" << std::endl;
tansheng *ptemp = ::new tansheng;//劫持
return ptemp;
//return NULL;
}
static void operator delete(void *p)
{
jisuqi--;
std::cout << "对象被销毁" << std::endl;
::delete p;
}
};
int tansheng::jisuqi = 0;
//类的内部new没有完成分配内存的动作
//通往全局的new的中间做了一个劫持
//空类占一个字节,表示自己存在
//构造和析构函数在代码区,sizeof求类的大小,不包括析构和构造函数
//类的对象,数据是独立的,代码是共享的
//没有分配内存,构造函数与析构函数无意义
void main()
{
tansheng *p1 = new tansheng;
//delete p1;
tansheng *p2 = new tansheng;
//delete p2;
tansheng *p3= new tansheng;
delete p3;
std::cout << tansheng::jisuqi << std::endl;
//std::cout << "类的大小" << sizeof(zeng) << std::endl;
std::cin.get();
}
对象数组
#include<iostream>
class tansheng
{
public: int*p;//成员变量
public:
int length;//默认私有
public :
tansheng()//构建类时自动初始化(构造函数),自动调用
{
std::cout << "谭胜被创建" << std::endl;
}
~tansheng() //删除的时候释放内存(析构函数),自动调用
{
std::cout << "谭胜傻逼" << std::endl;
std::cout << "谭胜被销毁" << std::endl;
}
};
void main11()
{
tansheng*p = new tansheng[10];
//delete p;错误 基本数据类型,可以直接delete,复杂必须delete[]
delete[]p;//正确
system("pause");
}
void main1234121243()
{
/*int *p = new int[80];
int(*px)[10] = (int(*)[10])p;//强制类型转换*///,正确
//int(*px)[10]=new int [80];这是错误的,new只分配线性的
int(*px)[10] = new int[8][10];
int data = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 10; j++)
{
px[i][j] = data++;
std::cout << " " << px[i][j];
}
std::cout << std::endl;
}
system("pause");
}
//总结
#include<iostream>
#include<stdlib.h>
//全局的new delete监视所有释放分配
//局部的new delete监视某个类的所有分配释放
//
void *operator new(size_t size)
{
if (size == 0)
{
return 0;
}
void *p = malloc(size);
std::cout << "全局被调用内存被分配" << p << std::endl;
return p;
}
void operator delete (void *p)
{
std::cout << "全局被调用内存被释放" << p << std::endl;
free(p);
}
void *operator new[](size_t size)
{
return operator new(size);//每个对象挨个调用已经重载好的new,调用构造
}
void operator delete[](void*p)
{
return operator delete(p);//每个对象挨个调用已经重载好的delete,调用析构
}
class tansheng
{
public:
static int jishuqi;//静态
int *p;
int length;
public:
tansheng()//构建的时候初始化
{
std::cout << "谭胜被创建" << std::endl;
}
~tansheng()//删除的时候释放内存
{
std::cout << "谭胜被销毁" << std::endl;
}
static void * operator new(size_t size)
{
jishuqi += 1;
std::cout << "对象被创建" << std::endl;
tansheng *ptemp = ::new tansheng;//劫持
return ptemp;
}
static void * operator new[](size_t size)
{
std::cout << "对象数组被创建" << std::endl;
return operator new(size);
}
static void operator delete(void *p)
{
jishuqi -= 1;
std::cout << "对象被销毁" << std::endl;
::delete p;//::全局
}
static void operator delete[](void *p)
{
std::cout << "对象数组被销毁" << std::endl;
return operator delete(p);
}
};
int tansheng::jishuqi = 0;
void main()
{
//int *p = new int[10];
//delete[]p;
tansheng *p1 = new tansheng[5];
delete[]p1;
system("pause");
}
void main1()
{
int *p = new int(8);
delete p;
system("pause");
}
//int *p=new int[10]
//delete []p;
宽字符
//设置本地化才可以显示中文
#include<locale>
Setlocale(LC_ALL,”chs”);//设置本地化
#include<iostream>
#include<stdlib.h>
#include<locale>
void main()
{
///设置本地化
setlocale(LC_ALL, "chs"); //LC_ALL代表宽字符 chs代表China
wchar_t *p1 = L"12345";
std::wcout << p1 << std::endl;
wchar_t *p2 = L"北京12341341";
std::wcout << p2 << std::endl;
system("pause");
}
BOOL
#include<iostream>
#include<stdlib.h>
void main()
{
//与优先级比2高
bool bl = 1 && 1 || 2 || -1 && 0;
std::cout << typeid(bl).name() << std::endl;
std::cout << bl << std::endl;
decltype(bl) bt(1 + 2 * 3 - 4 && 3 + 2 || -1);
std::cout << bt << std::endl;
system("pause");
}