C++视频课程小结(2)
C++远征之离港篇
章节介绍:
每章小结:
- 第一章:大致讲了一下本章会讲的内容:引用vs指针、const vs #define(这个我在C里都没用过)、函数变得更强大、内存管理要小心之类的。
- 第二章:按视频所说,引用就像别名一样,所以不能只有引用而没有本体,而且对引用的操作与对变量直接操作完全一样。引用的声明方法:
类型标识符 & 引用名 = 目标变量名
,如果是指针的引用则是类型标识符 * & 引用名 = 目标变量名
。然而我并没有搞懂引用到底有什么好处。视频接下来举了一些例子,有一个是引用作为函数的参数:
这让我想起了当初用指针做两个数的调换的优势体现在两个数比较大的时候,明显有效率的多,看样子引用也可以做到,看上去还更简洁。还有就是,如果去掉上图中右边函数形参中的两个&的话,实参并不会被交换,因为实参和形参是单向的值传递(不怎么用函数都忘记了)。还有一个是结构体引用:结构体的定义多了一个typedef
,还以为是C++有所不同,保险还是查了一下(后来发现C的书上就有,完全没印象。。。),发现比我想象得复杂得多:(来自http://www.cnblogs.com/qyaizs/articles/2039101.html后面的看不大懂就不写了。)
1、 首先:注意在C和C++里不同
在C中定义一个结构体类型要用
typedef
typedef struct Student
{
int a;
}Stu;
于是在声明变量的时候就可:`Stu stu1;`(如果没有`typedef`就必须用`struct Student stu1;`来声明)这里的`Stu`实际上就是`struct Student`的别名。`Stu==struct Student`
另外这里也可以不写`Student`(于是也不能`struct Student stu1;`了,必须是`Stu stu1;`)
typedef struct
{
int a;
}Stu;
但在c++里很简单,直接
struct Student
{
int a;
};
于是就定义了结构体类型`Student`,声明变量时直接`Student stu2;`*(这倒是和C不一样)*
2.其次:
在c++中如果用
typedef
的话,又会造成区别:
struct Student
{
int a;
}stu1;//stu1是一个变量
=======================
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型=struct Student
使用时可以直接访问stu1.a 但是stu2则必须先stu2 s2;然后s2.a=10;(上面的第一点里C讲了一大堆感觉就是第二点讲的意思:加不加就是类型和变量的区别)
感觉得视频里讲的有点少,就加了一些自己找的东西(<http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html>)。
一些说明:
例1:
int a; int &ra=a;
//定义引用ra,它是变量a的引用,即别名(1)&在此不是求地址运算,而是起标识作用。
(2)类型标识符是指目标变量的类型。
(3)声明引用时,必须同时对其进行初始化。
(4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。 ra=1; 等价于 a=1;
(5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra与&a相等。
(6)不能建立数组的引用。因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名。
引用应用:
引用作为参数
引用的一个重要作用就是作为函数的参数。以前的C语言中函数参数传递是值传递,如果有大块数据作为参数传递的时候,采用的方案往往是指针,因为 这样可以避免将整块数据全部压栈,可以提高程序的效率。但是现在(C++中)又增加了一种同样有效率的选择(在某些特殊情况下又是必须的选择),就是引用。
例2:
void swap(int &p1, int &p2)//此处函数的形参p1, p2都是引用
{ int p; p=p1; p1=p2; p2=p; }
为在程序中调用该函数,则相应的主调函数的调用点处,直接以变量作为实参进行调用即可(感觉有点绕不过来啊。。。),而不需要实参变量有任何的特殊要求。如:对应上面定义的swap函数,相应的主调函数可写为:
main( )
{
int a,b;
cin>>a>>b; //输入a,b两变量的值
swap(a,b); //直接以变量a和b作为实参调用swap函数
cout<<a<< ' ' <<b; //输出结果
}
上述程序运行时,如果输入数据10 20并回车后,则输出结果为20 10。
由例2可看出:
(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。(调用函数的时候偷偷给形参的引用初始化的意思吧)
(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给 形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效 率和所占空间都好。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用指针变量名的 形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。
(接下来的常引用、引用作为返回值和引用和多态,分别涉及到了const和函数等超纲的东西,就先不写了。)
引用小结:
(1)在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。
(2)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
为了记忆最后再来实际打一点(当然是调试过的,主要是单词老记错。。。)。
#include<stdlib.h>
#include<iostream>
using namespace std;
namespace exchange
{
void fun(int &a,int &b)
{
int c;
c=a;
a=b;
b=c;
}
}
typedef struct
{
int x;
int y;
}Coor;
int main()
{
using namespace exchange;
Coor C;
Coor & C1=C;
cin>>C.x>>C.y;
fun(C1.x,C1.y);
cout<<C.x<<" "<<C.y<<endl;
system("pause");
return 0;
}
- 第三章:C++语言const关键字。
感觉就是定义个常量而已(然而我一般都没用到常量),定义的一般格式就是const 数据类型 常量名=某个值;
(原来C里是#define 常量名 某个值
并没有分号,它是宏定义),定义指针常量的时候则有些不一样的地方:像const int *p
和int const *p
是等价的,而int const *p
和int * const p
则是不一样的。具体来说,定义为int const *p
时,可以对p进行赋值,而不可以对*p
进行赋值;定义为int * const p
时则可以对*p
赋值,而不可以对p赋值;如果是int const * const p
则两个都不能进行赋值。还有就是视频里提到了这两个代码:const int x=3;int *p=&x;
、int x=3;const int *p=&x;
,说是第一个的定义是错的,用一个指针变量指向常量会有风险,而第二个则可以,相当于用权限小的指向权限大的。最后视频还提到常引用的问题,感觉这个倒是有可能会用到,再和函数结合起来的话(但是形参定义成常引用的话,在函数里还能做什么操作啊)。 - 第四章:C++函数新亮点。
函数参数默认值。就是说在函数声明的时候(按视频说,定义的时候赋值的话有的编译器不接受)可以对参数赋值,而且要从右边开始,然后调用的时候无实参就用默认值,有实参就覆盖默认值。举个例子来说,有如下的代码:
#include<stdlib.h>
#include<iostream>
using namespace std; void fun(int i=10,int j=20,int k=30); int main()
{
fun();
fun(100);
fun(100,200);
fun(100,200,300); system("pause");
return 0;
} void fun(int i,int j,int k)
{
cout<<i<<","<<j<<","<<k<<endl;
}
运行结果:
这也便于理解默认值要从右边开始。
- 函数重载。就是说参数可辨(参数的类型和个数有差别)的函数可以使用同一个名称,调用函数的时候编译器会根据输入的参数来自行判断使用哪个函数(这倒是很方便)。
- 内联函数。定义一个内联函数只要在定义函数时加上内联函数的关键字inline
就好。内联函数的好处是效率高,具体是因为它省略了图中的②③两步:
但是使用内联函数有一定的条件:当函数逻辑简单且被循环调用时就很适合用内联函数来提高效率,但是递归函数无法使用内联,而且内联函数还是建议式的命令,最终由编译器决定,不适合的也会被当成一般函数来处理。
第五章:C++内存管理。
按视频所说,内存管理就是申请、归还内存资源。申请内存要用到运算符new
,归还内存要用到运算符delete
。具体来说,申请一个整型内存的代码是int *p=new int;
(int *p=new int (10);
则是申请的同时初始化为10),对应的释放内存只要delete p;
;还可以申请块内存,代码是int *p=new int [n];
(其中n表示申请的内存大小,感觉就是数组的长度),要注意的是释放块内存的代码是delete []p;
,不然的话就只有数组的第一个会被释放。这是内存管理的第一个注意事项,就是要一一对应,还包括(话说在C里面还是没用过):
第二点是内存的申请有可能会失败(像没有足够的内存给你申请时),要检查是否成功(具体就是指针是不是空指针)。第三点是,释放完内存后要把指针设置为空指针,这也是为了避免不必要的错误(据说释放两次会报错)。再来实际打一点代码:#include<stdlib.h>
#include<iostream>
using namespace std; int main()
{
int *p=new int[10]; if(p==NULL)
{
cout<<"内存申请失败"<<endl;
system("pause");
return 0;
} p[0]=10;
p[1]=20; //没有加*耶
cout<<p[0]<<","<<p[1]<<endl; delete []p;
p=NULL; system("pause");
return 0;
}
C++视频课程小结(2)的更多相关文章
- C++视频课程小结(3)
C++远征之封装篇(上) 章节介绍: 每章小结: 第一章:课程介绍. 按照惯例是章节的总介绍,内容明显多了很多(为了做作业我还要赶进度的说),主要说了:类和对象是本章的主角,然后还有很多配角,像数据成 ...
- C++视频课程小结(1)
C++远征之起航篇 章节介绍: 每章小结: 第一章:C++诞生于贝尔实验室,C++包含C语言. 第二章:介绍了IDE环境(虽然没怎么懂),还推荐使用visual stdio 2010 旗舰版(姑且下了 ...
- 慕课网:剑指Java面试-Offer直通车视频课程
慕课网:剑指Java面试-Offer直通车视频课程,一共有10个章节. 目录结构如下: 目录:/2020036-慕课网:剑指Java面试-Offer直通车 [6G] ┣━━第10章 Java常用类库与 ...
- DDD建模案例----“视频课程”场景
接触领域驱动设计DDD有一年多的时间了,中间看过不少书,参与过一些讨论(ENode QQ群).目前对DDD的认知还停留在理论阶段,所以对领域建模非常感兴趣,这里说的建模是指以DDD的思想为指导再加上D ...
- Asp.NET Core2.0 项目实战入门视频课程_完整版
END OR START? 看到这个标题,你开不开心,激不激动呢? 没错,.net core的入门课程已经完毕了.52ABP.School项目从11月19日,第一章视频的试录制,到今天完整版出炉,离不 ...
- 【学习记录】第一章 数据库设计-《SQL Server数据库设计和开发基础篇视频课程》
一.课程笔记 1.1 软件开发周期 (1)需求分析阶段 分析客户的业务和数据处理需求. (2)概要设计阶段 设计数据库的E-R模型图,确认需求信息的正确和完整. /* E-R图:实体-关系图(Ent ...
- 《Python从菜鸟到高手》已经出版,开始连载了,购买送视频课程
好消息,<Python从菜鸟到高手>已经出版!!! JetBrains官方推荐图书!JetBrains官大中华区市场部经理赵磊作序!送2400分钟同步视频课程!500个案例,400道P ...
- Spring Boot 实战与原理分析视频课程
Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...
- C++视频课程
一.视频课程 课程名称:C++学习教程 程序设计 C++基础教程 授课人:郭宏志 课程链接:http://study.163.com/course/courseMain.htm?courseId=63 ...
随机推荐
- LA 4725 (二分) Airport
题意: 有W.E两个跑道,在每个时刻每个跑道的飞机都从0开始编号,而且每个时刻都有Wi和Ei架飞机到达这两个跑道.而且每个时刻只能选择一个跑道的一架飞机起飞.问如何选择才能使得飞机的最大编号最小.(每 ...
- 在VMware 虚拟机中配置 windows2003系统的NLB负载均衡;0x800706D5错误的解决方法;没有接口可用于安装新的群集
首先在VM里面 我装了3个2003的系统, 分别为 webservice01 ,webservice 02 , 以及 webview 这3台. 前面两台用于配置负载均衡,后面的webview就是 ...
- Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法
$() 即调用了jQuery.fn.init方法 jQuery = function( selector, context ) { return new jQuery.fn.init( selecto ...
- I.MX6 Android backlight modify by C demo
/************************************************************************** * I.MX6 Android backligh ...
- (七)7.2 应用机器学习方法的技巧,准确率,召回率与 F值
建立模型 当使用机器学习的方法来解决问题时,比如垃圾邮件分类等,一般的步骤是这样的: 1)从一个简单的算法入手这样可以很快的实现这个算法,并且可以在交叉验证集上进行测试: 2)画学习曲线以决定是否更多 ...
- (二)深入梯度下降(Gradient Descent)算法
一直以来都以为自己对一些算法已经理解了,直到最近才发现,梯度下降都理解的不好. 1 问题的引出 对于上篇中讲到的线性回归,先化一个为一个特征θ1,θ0为偏置项,最后列出的误差函数如下图所示: 手动求解 ...
- 【Python】Python重新学习
<python基础教程(第二版)> http://www.cnblogs.com/fnng/category/454439.html 分片(后面取的是前一位) eg: >>&g ...
- Android中Bitmap, Drawable, Byte,ID之间的转化
Android中Bitmap, Drawable, Byte,ID之间的转化 1. Bitmap 转化为 byte ByteArrayOutputStream out = new ByteArray ...
- aspose.words复制插入同一word文档中的某个页面
选择word模板 Document doc = new Document(Server.MapPath("~\\templet") + "\\" + name. ...
- delete archivelog all 无法彻底删除归档日志?
最近在因归档日志暴增,使用delete archivelog all貌似无法清除所有的归档日志,到底是什么原因呢? 1.演示环境 SQL> select * from v$version whe ...