引用

C中指针的功能强大,使用起来繁杂,因为指针要控制的东西太多:有指针的类型,指针的解引用,指针空间内的值,它本身是有空间的,有自己的地址等。指针也是强大的,比如:我们要在函数之内,修改方法之外的值的话,必需用到指针。但这里指针的使用,使得我们要修改的类型,变成了另外一种类型(如:int*)由原来的类型变成了指针类型。

 引用  &  能实现指针一模一样的功能,但它不改变数据的状态(类型)。

用法:int val = 100;  int &refval = val ;

指针我们可以直接指向一个NULL,但引用必需要指向一个变量。这是与指针不一样的地方。引用是变量的别名。

1 引用是没能独立空间的,所以它一定要与一个变量绑定,才能共用一段空间。

2 引用确定后,它无法被更改。一旦经理室了一个对象,就无法再次赋值为别的对象。

上图所有针对refval的操作,都作用在绑定的变量val上。

3 引用,它与引用 的变量共用同一段空间

示例:

#include <iostream>
using namespace std; void Swap(int &rhs, int &lhs)
{
int tmp = rhs;
rhs = lhs;
lhs = tmp;
} int main()
{
int val = ;
int &refval = val ; int num = ;
//refval = num; //这里示范,相当于这样:val = num Swap(val,num);
cout << val << " " << num ; return ;
}

运行:  50      100

数据交换成功。

引用它是安全的,可以理解为阉割版的指针:

#include  <iostream>

void Swap(int &rhs,int &lhs)
{
int tmp = rhs;
rhs = lhs;
lhs = tmp;
} int main()
{
int val = ;
int &refval = val; //引用是变量的别名,更多是在语法层面的。
//它是没有独立空间的;
//引用确定后,它的值是不能更改的。
// 共用同一空间
int *pVal = &val; val = ;
std::cout << val; //
std::cout << refval; //
std::cout << pVal; //val地址
std::cout << *pVal; //50 //Swap(val, num); return ;
}

断点 运行:

再看:

运行:

再再看:

运行如下:

引用的意义在于:代码的可读性更强,并且安全,但凡一引用,永远无法更改。

提问:这两种写法正确吗?  1  // int &refval = 100;   2  //int *pval = &100;

这样子是不行的:  看1的代码,一个引用int &refval等于一个立即数100,立即数100是没有内存地址的,也就是没有空间的,虽然说引用没有独立的空间,但它指向一个变量后,也就是要有空间的,共享空间而已。这里立即数不在内存里面产生,在内存中没有空间,所以1的写法是错误的。

  看2的代码,左边是一个int * 的指针pval,等号后面,把100这个立即数的地址,赋值给左边的指针?~!立即数在寄存器里面产生,不在内存中存在。很显然,示例2的代码也是错误的。


复习C语言中 const 的用法

1  示例  代码:const int *pVal = &val;   请问:这段代码const修饰了什么?是什么不能修改?是地址pval,还是解引用的值不能修改?用编译器的贪心法则来套用:const先看左边,左边为空,那转向右边,第一个int ,再看第二个*,可以修饰,再看pVal,最后遇到赋值等号,那么const有效的修饰3个连接:int *pVal,得出结论:*pVal解引用的值被const修饰,值不能修改。

2 示例  代码:int const *pVal = &val;  这段代码又是什么不能修改?  当const在*号的左边时,和代码1一样。

3 示例 代码:  int * const pVal = &val;  当const在*号的右边时:(看口诀:左数右指。)那么就是这根“指针”本身不能被改变。就是指针里面的内存地址(俗称一根指针)。

 在C++中const 和&引用一块使用会产生什么化学反映呢?

示例  //const int &refval = val;   这里是什么无法修改呢?  A  值   B  地址

答案是:以上都不正确,因为const的引用,要指向const修饰的类型

如:const int num = 500; const int & refnum = num;  这样出现才是正确的。如果你要引用一个常量的话,前面一定要加上const修饰。


 

 

运行,交换成功!

函数void Swap(int &rhs, int &lhs);  相当于传递了指针地址,也就是说传递了引用 的共享空间,在C中我们用指针,C++中我们用引用。可以这么认为:它将函数形参实参化了。引用相当于直接传递了本身(地址)。好处就是:函数内将参数作为变量使用,作用于外部。

函数之间的值传递是通过栈来完成的,如果我要传递的是一个比较大的结构体,那么这里就可以使用“&引用”,传递地址以节省空间。

实际上我们想传递引用时,常见的情况下,只需要传递地址,数据并不想被修改,那么,引用要加上const 来修饰,以避免被修改的风险。而且下面调用函数时,并不用写上const对应参数,因为它会自动做一个提升。

引用还可以作为函数的返回

引用作为返回值的写法

看代码 1

#include  <iostream>

int array[] = { ,,,, };

int &Index(int index)
{
return array[index];
} int main()
{
Index() = ;
return ;
}

代码 2

#include  <iostream>

int array[] = { ,,,, };

int &Index(int index)
{
return array[index];
} int *Index()
{
retrun &array[];
} int main()
{ Index() = ;
*Index() = ; return ;
}

以上是返回引用与返回指针的写法。

这里打印指针和引用,直观的认识指针和引用之间的区别:

#include  <iostream>

int array[] = { ,,,, };

int &Index(int index)
{
return array[index];
}
int *Index()
{
return &array[];
} int main()
{ Index() = ;
*Index() = ; std::cout << array[] << " " << Index();
//100 //地址
int num = ;
int &ref = num, *p = &num;
std::cout << ref << p << *p;
//0 //地址// return ;
}

引用能不能取代指针呢?答:不能,因为引用不能指向推空间。

C++很强大:请看这行代码   int *&refp = p;

C++11中间的auto  自动推导所需类型

这里有行永远也不要写的代码:*p = num;  auto &refp = p;   永远不要拿一个指针去做它的引用。


 
类与对象
 

 

类:比如人类,虚的,抽象的,出现在人们口中,出现在纸上,是一个概念性的,属性的集合。

 
 对象:实体的,活生生的,能动能说能笑,吃喝拉撒……
 

 

 
 

 

C++中的类:公有  public :   私有   private :   默认私有。

私有属性只能类内部访问。

 

其实还有一种  protected  :    受保护的。

 

构造函数与析构函数

 

代码:

#include <iostream>

class MyString
{
char *str;
int len;
public:
MyString() //构造函数
{
std::cout << "MyString()被调用" << std::endl;
}
~MyString() //析构函数
{
std::cout << "~MyString()被调用" << std::endl;
}
int &Len()
{
return len;
}
}; int main()
{
MyString demo;
demo.Len() = ; return ;
}

断点运行:

构造函数与类名相同,没有返回值

你不写,编译器默认生成

当对象产生时,构造函数被调用。

 
 

析构函数    当对象销毁时,析构函数被调用

 

当你创建了构造函数,编译器不会再自动生成构造函数。

析构函数里面,写入释放内存的代码,是常见的手法。

 

我们无法直接:类.方法  因为类是虚的,是图纸,是设计方案,是汽车图纸,只有实体小车,才有车门,有方向盘,所以老司机要开车,首先要有个对象:一辆车。在计算机的世界里面,类不占内存,对象才占用内存。占用内存的,才是实体对象。

对象是实体的,就如一块实体的手表,手表设计图纸就是类,工厂按设计图纸加工,材料是各属性变量等,默认构造成一个什么样子,就有了构造函数,不合格就的产品要收回,就有了析构函数。所以每个手表(对象)就有初始的大致的模样和功能(构造函数 ),还有回收方法(析构函数),有些是在表面可见的,可以控制的(public权限),而有些是封闭在手表内部,是不可见的(private权限);

现得知一个类:构造函数带有参数,如果想创建不带任何参数的对象,两种方法:1  构造函数重载,加一个没有任何参数的构造函数;2  在现有的参数里面写入默认实参。

 

类  内部变量书写规范  加下划线

 

作业:

附上代码,以及一个小发现:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring> class MyString
{
char *_str;
int _len;
public:
MyString()
{
_str = new char[];
_len = ;
}
MyString(char *str)
{
_len = strlen(str);
_str = new char[_len+ sizeof(char)];
strcpy(_str, str);
}
~MyString() //析构函数
{
delete[]_str;
}
char *GetString()
{
return _str;
}
}; int main()
{
MyString demo1; MyString demo2(); //前者是新建一个以demo1命名的对象,后者是声明一个返回MyString类型的函数demo2(). MyString demo("I Love Mark");
std::cout << demo.GetString();
return ;
}

检验一下上面高亮的demo2,看它到底是对象,还是方法。

验证说明:demo2是方法,不是对象。

PoEdu - C++阶段班【Po学校】- 第3天的更多相关文章

  1. PoEdu - C++阶段班【Po学校】- Lesson03-4_构造函数&赋值函数&拷贝构造函数&学习方式 - 第6天

    PoEdu - C++阶段班[Po学校]- 第6天 课堂选择题目: 1  关于转换构造函数  ClassDemo demo = 1;  调用转换构造函数 2  关于拷贝赋值函数  demo =2; 首 ...

  2. PoEdu - C++阶段班【Po学校】- Lesson02_类与对象_第4天

    复习:上节作业讲解 注意点: 设计SetString()的时候,要注意重置原来的空间. char * SetString(const char *str) { _len = strlen(str); ...

  3. PoEdu - C++阶段班【Po学校】- 第1课

    1 C++开讲 C ++  伟大的编程语言:能提高程序运行效率,节约更多的资源,"正确的使用C++,能够抑制全球变暖问题". 2 C++能力雷达图 通过 1效率 2灵活度 3 抽象 ...

  4. PoEdu - C++阶段班- Lesson07 To Lesson10_C to C++

    07  重载导致的二义性 问题:为什么一定要重载呢?重载能方便我们注重函数的功能,当参数类型不确定时,我们能很便捷的利用重载的机制达到目的. 重载注意点:二义性 看代码: #include <c ...

  5. PoEdu - C++阶段班- Lesson02_C to C++

    1  原生bool类型 c++里面的bool类型才是真正原生的true和faul,比如常见的大写的"BOOL",它就不是原生的. 原生的与非原生的bool,它们的区别: 详细说下原 ...

  6. PoEdu- C++阶段班【Po学校】-Lesson03_构造函数精讲 - 第5天

    复习构造函数:1  与类同名   2  没有返回值   3  自动生成    4  手动后,不会自动生成    5  不在特定的情况下,不会私有  新建 类   两种方法示范   其一:在vs中选择类 ...

  7. PoEduo - C++阶段班【Po学校】-Lesson03-5_运算符重载- 第7天

    PoEduo - Lesson03-5_运算符重载- 第7天 复习前面的知识点 空类会自动生成哪些默认函数 6个默认函数    1  构造  2  析构   3  赋值  4 拷贝构造  5 oper ...

  8. 九、Python+Selenium模拟用QQ登陆腾讯课堂,并提取报名课程(练习)

    研究QQ登录规则的话,得分析大量Javascript的加密解密,比较耗时间.自己也是练习很少,短时间成功不了.所以走了个捷径. Selenium是一个WEB自动化测试工具,它运行时会直接实例化出一个浏 ...

  9. 九、Python+Selenium模拟登录

    研究QQ登录规则的话,得分析大量Javascript的加密解密,比较耗时间.自己也是练习很少,短时间成功不了.所以走了个捷径. Selenium是一个WEB自动化测试工具,它运行时会直接实例化出一个浏 ...

随机推荐

  1. Android 5.0属性

    //水波纹效果//v 指定控件 x屏幕的 x轴 y轴 endRadio 起始位置 水波半径Animator circularReveal = ViewAnimationUtils.createCirc ...

  2. modelsim(3) - summary ,issue,tips

    1) the OEM of modelsim is 10 times slower than offical questa 2)how to the file full path in the mod ...

  3. eclipse debug maven项目时出现缺少库的问题

    调试maven web项目时出现缺少库的情况导致项目无法启动  可是打包到tomcat发布却一切正常 后来在stackoverlow上找到了解决方案 项目右键属性->Deployment Ass ...

  4. 安装Maven

    下载进入官网下载页面:http://maven.apache.org/download.html我用的是windows,下载apache-maven-3.2.5-bin.zip: Maven 3.2. ...

  5. Myeclipse中打开接口实现类的快捷键

    Myeclipse中打开接口实现类的快捷键-----Ctrl + T Myeclipse中 Open Type快捷键-----Ctrl + Shift + T

  6. U盘安装WIN10专业版

    安装环境1个SSD,2个SATA盘. 安装时把2个SATA盘拔掉,并使SSD在BISO中的地位为0区的MASTER,否则安装时会出现,无法创建当前分区,和新建当前分区. 步骤:下载win10正式专业版 ...

  7. loadrunner ---模拟多IP登录

    1.打开HP LoadRunner ->Tools ->IP Wizard

  8. 机器学习--Classifier comparison

    最近在学习机器学习,学习和积累和一些关于机器学习的算法,今天介绍一种机器学习里面各种分类算法的比较 #!/usr/bin/python # -*- coding: utf-8 -*- "&q ...

  9. FastJSON 使用

    FastJSON是一个Java语言编写的高性能,功能完善,完全支持http://json.org的标准的JSON库.多了不说了,百度一下一大把. 在此,简单的总结一下自己用过,测试过的方法. 如果使用 ...

  10. Ruby-递归和尾递归

    递归和迭代的区别 递归: 1)递归就是在过程或函数里面调用自身; 2)在使用递归时,必须有一个明确的递归结束条件,称为递归出口. 迭代: 利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话 ...