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 ...
随机推荐
- HDU 1072 (不一样的入队条件) Nightmare
之前的BFS都是需要一个标记数组,但这个题不一样,因为可能一个格子不止走一次. 那么我们就要寻找新的入队条件:left比上次经过的时候大才入队(left表示上次经过该点时剩余的时间). 为什么呢?我们 ...
- 菜鸟学习笔记3——jQuery 选择器
jQuery 元素选择器 jQuery 使用 CSS 选择器来选取 HTML 元素. $("p") 选取 <p> 元素. $("p.intro") ...
- 【英语】Bingo口语笔记(70) - 最易忽略的2个连读技巧
- gridview自定义表头
gridview为我们提供了丰富的接口,用于满足自定义需求. 通常asp:gridview会根据绑定的列Columns自动生成表头,展现在前台元素. 序号 类别 有时候需要复杂一些的表头. 序号 类别 ...
- oracle----sqlldr用法
SQL*LOADER是ORACLE的数据加载工具,通常用来将操作系统文件迁移到ORACLE数据库中.SQL*LOADER是大型数据仓库选择使用的加载方法,因为它提供了最快速的途径(DIRECT,PAR ...
- 《C和指针》读书笔记 第2章-基本概念
原创文章,转载请注明出处:http://www.cnblogs.com/DayByDay/p/3936485.html
- 搭建Nginx(负载均衡)+Redis(Session共享)+Tomcat集群
一.环境搭建 Linux下Vagrant搭建Tomcat7.Java7 二.Nginx的安装配置与测试 *虚拟机下转至root sudo -i 1)下载并解压(目前官网最新版本) 创建安装目录:mkd ...
- Android内存控制小技巧-使用矢量图来节省你的内存并简化你的开发。
先上一个 位图和矢量图的 说明.http://zhidao.baidu.com/link?url=xwvs5CBzWeh15O3Ee4bICwCqg4PCQWwg5oZ0a6CVydbVZzufqrI ...
- js记录用户在网站的浏览记录和停留时间
by weber开发者 from http://weber.pub/ 本文地址: http://weber.pub/js记录用户行为浏览记录和停留时间/163.html 问题 公司想统计一个用户从进入 ...
- [转] 接触C# 反射 2
逆心 原文 反射基础,2013-4. 反射用于在程序运行过程中,获取类里面的信息或发现程序集并运行的一个过程.通过反射可以获得.dll和.exe后缀的程序集里面的信息.使用反射可以看到一个程序集内部的 ...