C++基础02-C++对c的拓展

变量名实质上是一段连续存储空间的别名,是一个标号(门牌号)

通过变量来申请并命名内存空间.

通过变量的名字可以使用存储空间.

变量名,本身是一段内存的引用,即别名(alias). 引用可以看作一个已定义变量的别名。

引用的语法:Type& name = var;

int a=10;  //c编译器分配4个字节内存, a内存空间的别名

int &b=a;  //b就是a的引用

3.1.3 规则

1 引用没有定义,是一种关系型声明。声明它和原有某一变量(实体)的关系。故而类型与原类型保持一致,且不分配内存。与被引用的变量有相同的地址。

2 声明的时候必须初始化,一经声明,不可变更

3 可对引用,再次引用。多次引用的结果,是某一变量具有多个别名

4 &符号前有数据类型时,是引用。其它皆为取地址

 

const int a;

int const b;

//第⼀个第⼆个意思⼀样 代表⼀个常整形数

const int *c;

//第三个 c是⼀个指向常整形数的指针(所指向的内存数据不能被修改,但是本⾝可以修改)

int * const d;

//第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)

const int * const e ;

//第五个 e⼀个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)

const 常量是由编译器处理的,提供类型检查和作用域检查

 #define 宏定义由预处理器处理,单纯的文本替换  

引用作为函数参数

       普通引用在声明时必须用其它的变量进行初始化,引用作为函数参数声 明时不进行初始化

引用作为函数的返回值(引用当左值)

I. 当函数返回值为引用时,

         若返回栈变量: 不能成为其它引用的初始值(不能作为左值使用)

         若返回静态变量或全局变量 可以成为其他引用的初始值(可作为右值使用,也可作为左值使用)

        如果返回值为引用可以当左值

        如果返回值为普通变量不可以当左值。

普通引用有自己的存储空间吗?

        1)引用在C++中的内部实现是一个常指针

               Type& name <===> Type* const name

        2)C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占 用的空间大小与指针相同

        3)从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。

这是C++为了实用性而做出的细节隐藏。

从右向左看,&或*哪个离变量近, 哪个便起主要作用。int*&a=p_a; 把int*看成类型

int  b=12;

int  &a=b;

int* p_a=&b;

int* &a=p_a;

const引用

const 引用有较多使用。它可以防止对象的值被随意修改。因而具有一 些特性。

(1)const 对象的引用必须是 const 的,将普通引用绑定到 const 对象是不 合法的。这个原因比较简单。既然对象是 const 的,表示不能被修改,引用当然 也不 能修改,必须使用 const 引用。实际上,

           const int a=1;

           int &b=a;

这种写法是不合法 的,编译不过。

(2)const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初 始化。这个是 const 引用与普通引用最大的区别。

          const int &a=2; 是合法的。

          double x=3.14;

          const int &b=a;

也是合法的。

//int &m = 41; //error , 普通引⽤ 引⽤⼀个字⾯量 请问字⾯量有没有内存地址

const int &m = 43; //c++编译器 会 分配内存空间

// int temp = 43

// const int &m = temp;

#include	<iostream>
using namespace	std;	
int	main(void)	
{	
//1>	⽤变量 初始化 常引⽤
int	x1	=	30;	
const int &y1=x1;	//⽤x1变量去初始化 常引⽤
//2>⽤字⾯量 初始化 常量引⽤
const int a	= 40;		//c++编译器把a放在符号表中
//int &m = 41;	//error	,	普通引⽤ 引⽤⼀个字⾯量 请问字⾯量有没有内存地址
26
const int &m = 43;		//c++编译器 会 分配内存空间
//	int	temp = 43
//	const int &m = temp;
return 0;	
}

 

const引用的原理

const 引用的目的是,禁止通过修改引用值来改变被引用的对象

结论:

1)const int & e 相当于 const int * const e

2)普通引用 相当于 int *const e

3)当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值

分配空间,并将引用名作为这段空间的别名

4)使用字面量对const引用初始化后,将生成一个只读变量

 

 

内存四区:

1引用的基本语法:

#if 1
#include<iostream>
using namespace std;
//1 引用没有定义, 是一种关系型声明。声明它和原有某一变量(实体)的关
//系。故 而类型与原类型保持一致, 且不分配内存。与被引用的变量有相同的地
//址。
//2 声明的时候必须初始化, 一经声明, 不可变更。
//3 可对引用, 再次引用。多次引用的结果, 是某一变量具有多个别名。
//4 & 符号前有数据类型时, 是引用。其它皆为取地址。
void test01() {int a = 10;int &b = a;cout << a << endl;  //10b = 20;cout << a << endl;   //20cout << b << endl;   //20a = 30;{int *p = &a; *p = 12;cout << *p << endl; //12cout << a << endl;  //12}cout << a << endl;   //12cout << b << endl;   //12}
void test02() {int a = 10;int *p = &a;*p = 12;cout << *p << endl; //12cout << a << endl;  //12
}void test03() {const int a = 10;int *p = (int *)&a;*p = 12;cout << *p << endl; //12cout << a << endl;  //10
}void test04() {int a = 10;int &b = a;int *p = &a;*p = 30;p = &b;*p = 20;int &re = a;re = 50;cout << a << endl;  //50cout << b << endl;  //50cout << re << endl;  //50int ff = 10;re = ff;cout << a << endl;  //10cout << b << endl;  //10cout << re << endl;  //10}void test05() {int	a=1, b=0;int	&r = a;r = b;	//错误,不可更改原有的引⽤关系//float &rr = b;	//错误,引⽤类型不匹配	cout<<&a<<&r<<endl;	//变量与引⽤具有相>同的地址。int	&ra = r;	//可对引⽤更次引⽤,表⽰	a	变量有两个别名,分别是	r	和	ra
}
void test06() {int a = 10;int &b = a;int c = 20;b = c;b = 50;cout << a << endl;  //50cout << b << endl;  //50cout << c << endl;  //20  b并不是c的引用}void test07() {int a = 10;int &b = a;b = 100;cout << a << endl;  //100cout << b << endl;  //100int c = 20;b = c;b = 200;cout << a << endl;  //200cout << b << endl;  //200cout << c << endl;  //20 c的值未更改 b并不是c的别名
}
int& test08() {int a;return a;   //返回的是a的别名,函数调用完释放a,那么a的引用将不知道指向何处,所以test08()值会乱码
}
int& test09() {int a=0;return a;   //返回的是a的别名,函数调用完释放a,那么a的引用将不知道指向何处,所以test08()值会乱码const int &a1 = 100;
}
int main() {//test01();//test02();//test03();//test04();//test05();//test06();//test07();int a = 100;test08() = a;//test08() = a  //修改局部变量的值 错误cout << test08() << endl; //-858993460cout << test09() << endl; //0   //不懂int a1= 100;test09() = a1;cout << test09() << endl; //0cout << a1 << endl;    //100return 0;
}
#endif

 2引用当函数参数

#if 1
#include<iostream>
using namespace std;
void change_value1(int c) { //int c=a; c是局部变量需要复制 重新开辟栈空间c = 100;
}
void change_value2(int *c) {//int *c=a; 指针c存放a的地址。改变*c就是改变a的值//不需要额外复制*c = 200;
}
void change_value3(int &c) { //int &c=a; 形参c是实参a的引用,不需要额外复制c = 300;
}void test01() {int a = 0;change_value1(a);cout << "change_value1:" << a << endl;  //0a = 0;change_value2(&a);cout << "change_value2:" << a << endl;  //200a = 0;change_value3(a);cout << "change_value3:" << a << endl;  //300
}struct student {int id;char name[64];
};
void PrintStudent1(student s) {   //不建议使用 值拷贝cout << s.id << "  " << s.name << endl;
}
void PrintStudent2(student *s) {cout << s->id << "  " << s->name << endl;
}
void PrintStudent3(student &s) {cout << s.id << "  " << s.name << endl;
}
void test02() {student s1 = { 10,"sdsd" };PrintStudent1(s1);  //不建议使用PrintStudent2(&s1);PrintStudent3(s1); 
}
int main() {//test01();test02();return 0;
}
#endif

3引用的本质

#if 1
#include<iostream>
using namespace std;//当研究引用时,可以将引用当做一个常指针研究
//当使用引用编程时,就把引用理解为变量的别名就OK了
struct typeA {int &a;
};
struct typeB {int *a;
};
//引用的所占用的大小 跟指针相等
void test01() {cout << "sizeof(struct typeA):" << sizeof(typeA) << endl;  //4 32位系统cout << "sizeof(struct typeB):" << sizeof(typeB) << endl;  //4 32位系统
}
struct student {int id;char name[64];
};
//引用声明时必须初始化 常量声明时也必须初始化 引用可能是常量
//引用可能是常指针 int * const p;
void modify1(int *const a) {  //int *const a=main::&a; 可以改变a的值但不能改变a指向*a = 300;//a++;   错误
}
void modify2(int &a) {  //int &a=main::a; //当我们将引用作为函数参数传递的时候,编译器会替我们将实参,取地址给引用a = 200;            //对一个引用操作 赋值时,编译器替我们隐藏*操作
}
void modifyStudent(int *const a) {  //int *const a 可以改变a的值但不能改变a指向*a = 300;//a++;   错误
}void test02() {int a = 10;int &re = a;int *const p = &a;
}
int main(){test01();return 0;
}
#endif

4常量指针

#if 1
#include<iostream>
using namespace std;
int main() {int const a = 0;  //在常量区int *const p1 = NULL; //在常量区//p1++; ERROR*p1 = 30;int const *p2 = NULL;  //在常量区p2++;//*p2 = 40; ERRORreturn 0;
}
#endif

5引用作为函数返回值

#if 1
#include<iostream>
using namespace std;int getA1() {int tempValue = 10;return tempValue;
}
void getA2(int *a) {*a = 20;
}int &getA3() {int a = 10;return a;  //int &temp=a;将temp传到外部 返回的是别名
}
int &getA4() {static int a = 10;return a;
}
char *getmen(int num) {char *p = NULL;p = (char *)malloc(num);return p;  //值拷贝
}int getmen2(char **pp, int num) {char *p = NULL;p = (char *)malloc(num);*pp = p;return 0;
}void test01() {int a = 0;a = getA1();  //将返回值10拷贝给了a。要是有多个结构体会很浪费空间char *pp = NULL;pp = getmen(10);int main_a = 0;main_a = getA3();  //main_a=temp; 值拷贝cout << main_a << endl;  //10cout << main_a << endl;  //10//引用作为返回值,不要返回局部变量的引用。否则可能会出错 getA3函数被回收(没有权限访问,之前的变量覆盖)//引用如果当函数返回值的话,函数可以当左值int &main_a_re = getA3();cout << main_a_re << endl; //10cout << main_a_re << endl;  //-858993460int &main_a_re1 = getA4(); cout << main_a_re1 << endl;  //10cout << main_a_re1 << endl;   //10cout << main_a_re1 << endl;   //10getA4() = 1000;
}int main() {test01();return 0;
}
#endif

6引用指针

#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;struct teacher {int id;char name[64];
};
int get_mem(struct teacher** tpp) {teacher *tp = NULL;tp = (teacher*)malloc(sizeof(teacher));if (tp == NULL) {return 0;}tp->id = 100;strcpy(tp->name, "li4");*tpp = tp;return 0;
}
void Free_teacher(struct teacher **tpp) {if (tpp == NULL) {return;}struct teacher *tp = *tpp;if (tp != NULL) {free(tp);*tpp = NULL;}
}
void test01() {struct teacher *tp = NULL;get_mem(&tp);cout << tp->id << " " << tp->name << endl;Free_teacher(&tp);}
int get_mem2(struct teacher * &tp) { //struct teacher *为整体相当于inttp = (struct teacher *)malloc(sizeof(struct teacher));if (tp == NULL) {return -1;}tp->id = 1000;strcpy(tp->name, "wangwu");return 0;}
void Free_teacher2(struct teacher * &tp) {if (tp != NULL) {free(tp);tp = NULL;}}
void test02() {struct teacher *tp = NULL;get_mem2(tp);cout << tp->id << " " << tp->name << endl;Free_teacher2(tp);
}
int main() {test01();test02();return 0;
}
#endif

7const引用

#if 1
#include<iostream>
using namespace std;
void test01() {//如果对一个常量进行引用,则必须是一个const引用//相反 如果一个普通变量,用一个const引用是可以的const int a = 10; //安全性较高//int &b = a;  //错误 将 "int &" 类型的引用绑定到 "const int" 类型的初始值设定项时,//限定符被丢弃	03C++对C的拓展const int &re = a;int b = 20;  //安全性较低const int &re2 = b;// ret2 = 200; 错误b = 30;cout << b << endl;    //30cout << re2 << endl;  //30 const引用的目的是,禁止通过修改引用值来改变被引用的对象。//但可以通过改变被引用的对象改变引用值}void test02() {//int &ref = 10; //错误 引用了不合法的内存 不可以const int &ref = 10; //加入const后,编译器处理方式为:int tmp=10;const int &ref=tmp;对临时变量的引用//ref =10;  //错误int *p = (int*)&ref;*p = 1000;cout << ref << endl;  //1000
}//引用使用场景:通常用来修饰形参
void showValue(int &val) {val += 1000;  //如果只是想显示内容 而不进行修改就使用const进行修饰cout << "value:" << val << endl;
}void showValue(const int &val) {//val += 1000;  //编译错误cout << "value:" << val << endl;
}void test03() {int a = 10;showValue(a);  //1010
}
int main() {test01();cout << "--------" << endl;test02();cout << "------------" << endl;test03();return 0;
}
#endif

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567903.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab在电力系统故障的应用,MATLAB在电力系统故障分析中的应用

第5章MATLAB在电力系统故障分析中的仿真实例 5 1无穷大功率电源供电系统三相短路仿真5 2同步发电机突然短路的暂态过程仿真5 3小电流接地系统单相故障 5 1无穷大功率电源供电系统三相短路仿真 5 1 1无穷大功率电源供电系统三相短路的暂态过程5 1 2无穷大功率电源供电系统仿真模…

C++基础03-C++对c的拓展-函数

一、内联函数 c 语言中有宏函数的概念。宏函数的特点是内嵌到调用代码中去,避免了函数调用 的开销。但是由于宏函数的处理发生在预处理阶段,缺失了语法检测 和有可能带来的语 意差错。 特点&#xff1a; 1&#xff09;内联函数声明时inline关键字必须和函数定义结合在一起&a…

php小程序onload,微信小程序 loading 组件实例详解

这篇文章主要介绍了微信小程序 loading 组件实例详解的相关资料,需要的朋友可以参考下loading通常使用在请求网络数据时的一种方式&#xff0c;通过hidden属性设置显示与否主要属性&#xff1a;wxml显示loading正在加载jsPage({data:{// text:"这是一个页面"hiddenLo…

机器学习之实验过程02

机器学习之实验过程-数据清理 from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_errordata_path = /home/py/Work/机器学习/labs/data/Feedback.csv df = pd.read_csv(data_path) df.head() print (df.tail()) rename_pai…

C++基础04-类基础

一、类和对象 面向对象三大特点&#xff1a;封装、继承、多态。 struct 中所有行为和属性都是 public 的(默认)。C中的 class 可以指定行为和属性的访问方式。 封装,可以达到,对内开放数据,对外屏蔽数据,对外提供接口。达到了信息隐蔽的功能。 class 封装的本质,在于将数…

matlab 矩阵位移法编程 结构力学,matlab 矩阵位移法编程 结构力学

矩阵位移法编程大作业(091210211)一、编制原理本程序的原理是基于结构力学矩阵位移法原理&#xff0c;以结构结点位移作基本未知量&#xff0c;将要分析的结构拆成已知节点力—结点力位移关系的单跨梁集合&#xff0c;通过强令结构发生待定的基本未知位移&#xff0c;在各个单跨…

C++混淆点-构造函数参数

#include<iostream> using namespace std;class Test { public://Test(int x, int y) { //或者将形参名不要等于数据成员名// //x x; //自赋值 错误// //y y;// this->x x; //正确 形参a屏蔽了成员变量a&#xff0c;所以必须用this指针索引&#xff0c;这样程序直…

php 静态页面模板类,dedetag.class.php 静态模板类

类文件include/dedetag.class.php这个文件是dedecms V5.3及之前版本使用的主要的模板类&#xff0c;它是解析式模板类&#xff0c;并非编译式的(区别是前者通过获得标签位置进行内容替换&#xff0c;后者是直接解析式PHP代码&#xff0c;二次执行)一、模板语法织梦模板引擎是一…

C/C++混淆点-字符串指针

c语言中没有字符串的类型&#xff0c; 所以对字符串操作&#xff0c;有两种形式:可以用字符指针&#xff0c;或者字符串数组&#xff08;这里的指针变量c, 系统会为其重新分配内存) &#xff08;1&#xff09;用字符数组存放一个字符串 char string[]"Linux C"; pri…

python 文件上传下载,python实现上传下载文件功能

最近刚学python,遇到上传下载文件功能需求&#xff0c;记录下&#xff01;django web项目&#xff0c;前端上传控件用的是uploadify。文件上传 - 后台view 的 Python代码如下&#xff1a;csrf_exemptrequire_http_methods(["POST"])def uploadFiles(request):try:use…

C++基础05-类构造函数与析构函数

总结&#xff1a; 1、类对象的作用域为两个{}之间。在遇到}后开始执行析构函数 2、当没有任何显式的构造函数&#xff08;无参&#xff0c;有参&#xff0c;拷贝构造&#xff09;时&#xff0c;默认构造函数才会发挥作用 一旦提供显式的构造函数&#xff0c;默认构造函数不复…

PHP网站配置项,Thinkphp5通用网站后台配置项的动态添加及更新

一、引入无论平时我们自己制作&#xff0c;还是浏览别人的网站&#xff0c;它都具有其相应的一些共用的、通用的属性&#xff0c;比如&#xff1a;网站的名字&#xff0c;关键字、备案号、分页数量、是否开启缓存等信息。一些网站可能将配置项写死在后台&#xff0c;无法动态更…

C++基础06-类与对象之new和malloc

1、C和C动态分配内存区别&#xff1a; 在C语言中是利用库函数malloc和free来分配和撤销内存空间的。 C提供了较简便而功能较强的运算符new和delete来取代 malloc和free函数。 new和delete是运算符&#xff0c;不是函数&#xff0c;因此执行效率高。 2、new和delete的用法 &l…

php获取数组中的全部可以吗,php获取数组中所有值的方法

php的数组操作函数array_values 可以提取一个数组中所有元素值&#xff0c;具体的使用方法&#xff0c;可以参考下面的教程。array_values() 函数的作用是返回数组中所有元素的值&#xff0c;使用起来非常简单&#xff0c;只有一个必选参数&#xff0c;就可以返回一个包含给定数…

C++基础07-类之静态成员变量和成员函数

总结&#xff1a; 1、静态数据成员和静态成员函数属于整个类而不是某个对象 即使没有定义对象&#xff0c;静态成员也是存在的 2、static 成员类外存储,求类大小,并不包含在内。 &#xff08;因为存储在全局区&#xff0c;而类一般存储在栈区&#xff09; 3、静态数据成员在…

oracle 查询cpu 100%,Oracle 11g中查询CPU占有率高的SQL

oracle版本&#xff1a;oracle11g背景&#xff1a;今天在Linux中的oracle服务上&#xff0c;运用top命令发现许多进程的CPU占有率是100%。操作步骤&#xff1a;以进程PID:7851为例执行以下语句&#xff1a;方法一&#xff1a;(1)通过PID&#xff0c;查得相对应的系统进程对应的…

C++基础08-this指针-const修饰成员函数-函数返回引用/值

一、this指针 1、C类对象中的成员变量和成员函数是分开存储的。C语言中的内存四区模型仍然有效&#xff01; 2、C中类的普通成员函数都隐式包含一个指向当前对象的this指针。 3、静态成员函数、成员变量属于类 4、静态成员函数与普通成员函数的区别 静态成员函数不包含指…

oracle 10046详解,Oracle 10046事件详解

10046事件说明10046事件是Oracle提供的内部事件&#xff0c;是对SQL_TRACE的增强.10046事件可以设置以下四个级别:1 - 启用标准的SQL_TRACE功能,等价于sql_trace4 - Level 1 加上绑定值(bind values)8 - Level 1 等待事件跟踪12 - Level 1 Level 4 Level 8类似sql_trace&…

C++基础09-货物售卖和MyArray实现

1、货物出货与进货 #if 0 #include<iostream> using namespace std; /* 某商店经销一种货物。货物购进和卖出时以箱为单位。各箱 的重量不一样&#xff0c;因此商店需要记录目前库存的总重量&#xff0c;现在用 C模拟商店货物购进和卖出的情况 */ class Goods { public:…

oracle+导入emp,Oracle数据库导入导出emp文件

首先询问对方数据库的表空间名称和大小&#xff0c;然后在你的oracle中建立相应表空间&#xff0c;最后使用命令导入、导出数据。补充&#xff1a;1.要新建一个数据库&#xff1b;Oracle数据导入导出imp/exp就相当于oracle数据还原与备份。exp命令可以把数据从远程数据库服务器…