一:引用

概念:是给一个已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和引用的变量公用一块内存空间。

例如:

  类型& 引用变量名(对象名)= 引用实体

  int& a = b;

引用类型必须和引用实体是同种类型的。

特性:

  1. 引用在定义时必须初始化

  2. 一个变量可以有多个引用

  3. 引用一旦引用一个实体,再不能引用其他实体

引用适用场景:

  1.做参数  void Swap(int& left, int& right)

  2.做返回值  int& TestRefReturn(int& a) { return a;}

注意:如果函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型 返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。

引用与指针的区别:

  1.语法上:

    引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

  2.底层实现上:

    引用实际是有空间的,因为引用是按照指针方式来实现的。

引用和指针的不同点:

  1. 引用在定义时必须初始化,指针没有要求

  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

  3. 没有NULL引用,但有NULL指针

  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4 个字节)

  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

  6. 有多级指针,但是没有多级引用

  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理

  8. 引用比指针使用起来相对更安全。

二:内联函数

  在学习C语言的时候,我们已经学习过了宏函数,但是宏函数的缺点太多,而在C++中,引用了内联函数来解决这个问题。

学习前先回顾一下宏函数的实现与优缺点:

实现比较大小的宏函数:  #define MAX(a, b) ((a) > (b) ? (a) : (b))

实现加和运算的宏函数:  #define ADD(a, b) ((a) + (b))

优点:

  1. 提高了程序的可读性,同时也方便进行修改;

  2. 提高程序的运行效率:使用带参的宏定义既可完成函数调用的功能,又能避免函数的出栈与入栈操作,减少系统开销,提高运行效率;

  3. 宏是由预处理器处理的,通过字符串操作可以完成很多编译器无法实现的功能。比如##连接符。

缺点:

  1. 由于是直接嵌入的,所以代码可能相对多一点;不方便调试宏。(因为预编译阶段进行了替换)

  2. 嵌套定义过多可能会影响程序的可读性,可维护性差,容易误用。

  3. 没有类型安全的检查 ,对带参的宏而言,由于是直接替换,并不会检查参数是否合法,存在安全隐患。

    补充:预编译语句仅仅是简单的值代替,缺乏类型的检测机制。这样预处理语句就不能享受C++严格的类型检查的好处,从而可能成为引发一系列错误的隐患。

宏函数带来的是大大小小的坑,少一个括号,就有可能进入运算符优先顺序问题的坑,但C++中使用了内联函数要比宏函数好太多

  以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销, 内联函数提升程序运行的效率

特性: 

  1. inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使 用作为内联函数。

  2. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等 等,编译器优化时会忽略掉内联。

  3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找 不到

 三:auto关键字:

  在早期的c/c++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,但遗憾的是一直没有人去使用它。

  c++11中新的含义是:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

注意:在使用auto的关键字来定义变量的时候要对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为量实际的类型。

  auto的使用细则:

  1. auto与指针和引用结合起来使用---用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

 #include<iostream>
using namespace std; int main()
{
int x = ;
auto a = &x;
auto* b = &x;
auto& c = x; cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl; *a = ;
*b = ;
c = ; return ;
}

  2.在同一行定义多个变量

  当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个 类型进行推导,然后用推导出来的类型定义其他变量。

  auto a = 1, b = 2;

  auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同

  3.auto不能推导的场景

    1.auto不能作为函数的参数

 // 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导 
2 // void TestAuto(auto a) {}

    2.auto不能直接用来声明数组

 void TestAuto() {    
int a[] = {,,};    
auto b[] = {,,};
}//这里auto会报错

    3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法

    4. auto在实际中常见的优势用法就是跟以后会讲到的C++11提供的新式for循环,还有lambda表达式等进 行配合使用。

    5. auto不能定义类的非静态成员变量

    6. 实例化模板时不能使用auto作为模板参数

四:范围for循环

  对于一个有范围的循环如果由程序员自己来说明范围不仅比较麻烦,而且还会出错,在C++11中引入了基于范围的for循环,for循环后面额括号由冒号“:”分割为两部分:第一部分式范围

内用于迭代的变量,第二 部分则表示被迭代的范围。

 void TestFor() {
int array[] = { , , , , };
for (auto e : array)
{
e *= ;
printf("%d", e);
} for (auto e : array)
cout << e << " "; return;
}

范围for的使用条件:

  1. for循环迭代的范围必须是确定的

    对于数组而言,就是数组中第一个元素和后一个元素的范围;对于类而言,应该提供begin和end的方法, begin和end就是for循环迭代的范围。

 void TestFor(int array[])
{
for (auto& e : array) //这里没有合适的begin函数,所以会报错
cout << e << endl;
}

  2. 迭代的对象要实现++和==的操作。

五:指针控制

  在C语言中,我们习惯于使用NULL来给指针初始化,NULL实际上是一个宏,被定义为字面值常量0,或被定义为一个无类型指针(void*)的常量。我们的本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下 将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void *)0。

  为了考虑兼容性,C++11并没有消除常量0的二义性,C++11给出了全新的nullptr表示空值指针。C++11为什么 不在NULL的基础上进行扩展,这是因为NULL以前就是一个宏,而且不同的编译器厂商对于NULL的实现可能 不太相同,而且直接扩展NULL,可能会影响以前旧的程序。因此:为了避免混淆,C++11提供了nullptr, 即:nullptr代表一个指针空值常量。nullptr是有类型的,其类型为nullptr_t,仅仅可以被隐式转化为指针类 型,nullptr_t被定义在头文件中:typedef decltype(nullptr) nullptr_t;

  注意:  

    1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。

    2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。

    3. 为了提高代码的健壮性,在后续表示指针空值时建议好使用nullptr。

C++入门基础知识(二)的更多相关文章

  1. python入门基础知识二(字符串的常用操作方法)

    下标/索引: a = "I'm interested in Python." print(a[4]) i # 英文的字符串每一个下标/索引对应一个字母(含标点) a = '我喜欢p ...

  2. USB入门基础知识(转)

    源:USB入门基础知识 相关名词: 主机(Host) 设备(Device) 接口(Interface) 管道(Pipe) 管道是主机与设备端点数据传输的连接通道,代表了主机的数据缓冲区与设备端点之间交 ...

  3. React Native 入门基础知识总结

    中秋在家闲得无事,想着做点啥,后来想想,为啥不学学 react native.在学习 React Native 时, 需要对前端(HTML,CSS,JavaScript)知识有所了解.对于JS,可以看 ...

  4. java 基础知识二 基本类型与运算符

    java  基础知识二 基本类型与运算符 1.标识符 定义:为类.方法.变量起的名称 由大小写字母.数字.下划线(_)和美元符号($)组成,同时不能以数字开头 2.关键字 java语言保留特殊含义或者 ...

  5. Linux入门基础知识

    注:内容系兄弟连Linux教程(百度传课:史上最牛的Linux视频教程)的学习笔记. Linux入门基础知识 1. Unix和Linux发展历史 二者就像父子关系,当然Unix是老爹.1965年,MI ...

  6. 菜鸟脱壳之脱壳的基础知识(二) ——DUMP的原理

    菜鸟脱壳之脱壳的基础知识(二)——DUMP的原理当外壳的执行完毕后,会跳到原来的程序的入口点,即Entry Point,也可以称作OEP!当一般加密强度不是很大的壳,会在壳的末尾有一个大的跨段,跳向O ...

  7. Greenplum入门——基础知识、安装、常用函数

    Greenplum入门——基础知识.安装.常用函数 2017年10月08日 22:03:09 在咖啡里溺水的鱼 阅读数:8709    版权声明:本文为博主原创,允许非商业性质转载但请注明原作者和出处 ...

  8. Python入门基础学习 二

    Python入门基础学习 二 猜数字小游戏进阶版 修改建议: 猜错的时候程序可以给出提示,告诉用户猜测的数字偏大还是偏小: 没运行一次程序只能猜测一次,应该提供多次机会给用户猜测: 每次运行程序,答案 ...

  9. 1)Linux程序设计入门--基础知识

    )Linux程序设计入门--基础知识 Linux下C语言编程基础知识 前言: 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将 会学到以下内容: 源程序编译 Makef ...

  10. Dapper基础知识二

    在下刚毕业工作,之前实习有用到Dapper?这几天新项目想用上Dapper,在下比较菜鸟,这块只是个人对Dapper的一种总结. 2,如何使用Dapper?     首先Dapper是支持多种数据库的 ...

随机推荐

  1. Linux安装软件的时候出现乱码?

    在Linux的中文操作系统下使用xmanager进行软件安装的时候,可能出现乱码界面,可以通过以下方法进行解决 1 修改环境属性  vi /etc/sysconfig/i18n LANG=" ...

  2. Netfilter 之 五个钩子点

    概述 在协议栈的三层IPv4(IPv6还没看,不清楚)数据包的处理过程中,可能经过Netfilter的五个钩子点,分别为NF_INET_PRE_ROUTING.NF_INET_LOCAL_IN.NF_ ...

  3. LeetCode 128. 最长连续序列(Longest Consecutive Sequence)

    题目描述 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 [1 ...

  4. mysql if--else

    SQL之case when then用法 case具有两种格式.简单case函数和case搜索函数. --简单case函数 case sex when '1' then '男' when '2' th ...

  5. 解决ssh连接超时(ssh timeout)的方法

    echo export TMOUT=1000000 >> /root/.bash_profile (可设置为-1为永不超时) cat /root/.bash_profile source ...

  6. Ubuntu16.04.3安装并配置samba方法

    目的:单个Linux用户可以在windows电脑上通过映射网络驱动器的方式来访问自己的工作目录. 方法如下: 1.安装smb服务器:apt-get install samba2.安装smb支持的文件系 ...

  7. Event事件与协程

    1.Event事件 Event事件的作用: - 用来控制线程的执行. - 由一些线程去控制另一些线程. 2.进程池与线程池 1)什么是进程池与线程池? 进程池与线程池是用来控制当前程序允许创建(进程/ ...

  8. selenium 等待时间

    三种时间模式:1.隐性等待:①等待页面所有元素都加载完才执行下一步,如果在设定的时间内没有加载完成所有元素,则抛出异常②隐式等待对整个driver周期都起作用,即设置一次后,所有执行都会有效from ...

  9. DBUtil连接数据库

    1. SQL server连接: 数据库不同架包就不同 SQL server 使用的架包是(sqljdbc4.jar) 2. Mysql (MariaDB同理) SQL server 使用的架包是(m ...

  10. Pytorch-属性统计

    引言 本篇介绍Pytorch属性统计的几种方式. 统计属性 求值或位置 norm mean sum prod max, min, argmin, argmax kthvalue, topk norm ...