C++视频学习第2天





上午

 

高级引用:

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.不能包含switchgoto

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");





}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值