第二章 变量和基本类型

引用

  1. 引用定义的时候必须初始化。

  2. 引用初始化之后无法重新绑定到其它对象上。

  3. 引用本身并不是对象,所以没有指向引用的引用(不管如何多层引用,引用的还是源对象)

下面用一个简单的例子说明:

int a=1;
int& b=a;
cout<<&a;//00D4FE0C
cout<<&b;//00D4FE0C

可以看出对源对象a进行取地址和对b进行取地址的结果是一样的(实际上,引用的本质就是一个常量指针,即 int * const ptr类型

指针

  1. 指针本身就是个对象,允许对指针本身进行复制和拷贝操作。
  2. 指针定义时可以不赋初值,也可以指向nullptr,同时,其值也可以为未确定的值。
  3. 指针在其生命周期内可以指向不同的对象。

下面用一个简单例子说明:

int a=1;
int& b=a;
cout<<&a;//012FFD64
cout<<&b;//012FFD58

可以看出指针本身的地址和源对象的地址是不一样的,这是指针和引用的一个重要区别。

nullptr和NULL

nullptr是C++ 11 引入的新的关键字,而NULL是一个值为0的预处理变量,即:

#define NULL 0

在程序中最好使用nullptr关键字而非NULL,例如下面的例子:

#include <iostream>

void go(int num)
{
std::cout << "number" << std::endl;
} void go(void *p)
{
std::cout << "ptr" << std::endl;
} void main()
{
void *p = NULL; go(p);//ptr go(NULL);//number 得到的很有可能不是想要的答案 go(nullptr);//ptr system("pause");
}

void*指针

void*是一种特殊的指针类型,可以存放任意对象的地址,但是我们不了解其中存放的对象到底是什么类型的,我们可以用此指针来保存对象,而void表明我们我们用什么类型来解释这段存储空间中的对象(包括对象的长度),但我们无法对这个对象进行操作,因此在进行对象操作之前我们需要先对该指针进行类型转换。

int a=1;
void* b=&a;
cout << *(int*)b << endl;// 1

const限定符

const关键字用来表示一个常量,例如:

const int a=100;

编译器会在编译过程中把所有用到这个变量的地方全部替换成常数100。

默认情况下,const对象仅仅在当前文件内有效,如果多个文件中出现了同名的const变量,那么等于在不同文件中分别定义了独立的变量。(如果需要多个文件之间共享,那么我们需要使用extern关键字)

  • const结合指针

通过下面的代码区分const结合指针的区别:

int a=10;
const int * ptr=&a;// ptr本身可以指向别的对象,但不能通过ptr修改a的值
int const * ptr=&a;// 同上
int * const ptr=&a;// ptr本身不能改变,但是可以通过ptr修改a的值

类型别名

  • typedef

我们可以使用typedef来定义类型别名,这样我们就可以把越写越长的变量类型用短的单词代替,例如:

typedef int in;//in就是int的别名
typedef in i,*ptr;//i就是int的别名,ptr是int*的别名
#include <iostream>
using namespace std;
class A
{
public :
void test() { cout << 1; }
};
int main()
{
auto i=new A();
typedef void (A::*ptr)(); //ptr为指向A成员函数的指针类型,指向的函数的参数和返回值都为空
ptr a= &A::test;
(i->*a)();//输出1
}

同时我们需要注意typedef与define的一个重要区别:

typedef char* type;
#define def char*
type i1, i2; // i1 和 i2 均为指向 char 的指针
def j1, j2; // j1 为指向 char 的指针, 但 j2 为char 型变量
  • using

C++11新标准提出了新的方法,使用using来取别名:

using newInt= int;
newInt a=10;

auto类型说明符

自动分析表达式类型。

auto i=1;//int类型
  • 一般会忽略顶层const,保留底层const

顶层const:指针本身是常量;

底层const:指针指的对象是常量;

int i=0;
int * const p1=&i; //这是顶层const,不能改变p1的值
const int ci=42; //顶层const,不能改变ci的值
const int *p2=&ci; //底层const,不能改变p2的值
const tint * const p3=p2;//左边是底层const,右边是顶层const
const int & r=ci; //用于声明引用的都是底层const

个人理解:定义的变量本身不能改变,则为顶层const,反之则为底层const(引用除外,引用都是底层const)

再看auto推断规则:

int i=1;
const int ci=i;
const int &cr=ci;
auto b=ci;//b是一个整数,顶层const忽略
auto c=cr;//c是一个整数,cr是ci别名,ci是顶层const
auto d=&i; //d是一个整型指针
auto e=&ci; //e是一个整型常量指针,对常量对象取地址是一种底层const,也就是const int* e=&ci;

再看一个例子:

int a=1;
const int* ptr1=&a;
auto res1=ptr1;//底层const保留,res1类型为const int* int* const ptr2=&a;
auto res2=ptr2;//顶层const忽略,res2类型为int*

如果希望推到出的auto类型是一个顶层const,那么需要明确指出:

const auto f=ci;//这时候才会带上const,f类型为const int

decltype

decltpye用于选择并返回操作数的数据类型,在这个过程中编译器分析表达式得到类型,但是不计算表达式实际的值。

decltype(function()) sum=x;	//sum的类型就是function函数返回值的类型
  • decltype和auto的区别

decltype返回该变量的类型,包括顶层const和引用在内。

const int ci=0,&cj=ci;
decltype(ci) x=0; // x的类型是const int
decltype(cj) y=x; // y的类型是const int&,y绑定到变量x
decltype(cj) z; // 错误,z是一个引用,必须初始化

需要指出,引用从来都是作为其所指对象的同义词出现,只有用在decltype处是个例外。

此外,对于decltype所用的表达式来说,多加了一对括号和不加括号时会有区别,如果给变量加上了一层或者多层的括号,那么编译器会把它当作一个表达式,变量时一种可以作为赋值语句左值的特殊表达式,所以这样的decltype会得到引用类型。

decltype((i)) d;	// 错误,d是int&,必须初始化
decltype(i) e; // 正确,e是一个int

decltype((variable))的结果永远是引用,而decltype(variable)的结果只有在variable本身是一个引用时才是引用。

预处理器

C++程序可以使用#define指令把一个名称设定为预处理变量,用#ifdef表示在变量定义的时候为真,#ifndef为当变量未定义时为真,一旦检查结果为真,则执行后续操作到#endif为止。

#ifndef HEAD_H
#define HEAD_H ... your code... #endif

注意在VS中也可以使用#pragma once来表示只编译一次,但是只在windows下生效,无法跨平台。

[C++Primer] 第二章 变量和基本类型的更多相关文章

  1. <<C++ Primer>> 第二章 变量和基本类型 术语表

    术语表 第 2 章 变量和基本类型 地址(address): 是一个数字,根据它可以找到内存中的一个字节    别名生命(alias declaration): 为另一种类型定义一个同义词:使用 &q ...

  2. C++ Primer 笔记(2)第二章 变量与基本类型

    第二章 变量与基本类型 1.基本内置类型包括算术类型和空类型,算术类型分为两类:整型(包括字符和布尔类型)和浮点型: 2.布尔类型(bool)的取值是真(true)或者假(false): 3.字面值常 ...

  3. 《C++ Primer》读书笔记—第二章 变量和基本类型

    声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程. 1.8比特的char类型计算机表示的实际范围是-12 ...

  4. C++ Primer 读书笔记 第2章 变量和基本类型

    C++ Primer 第二章 变量和基本类型 2.1 基本内置类型 C++定义了一组表示整数.浮点数.单个字符和布尔值的算术类型(arithmetic type),此外还定义了Void类型. 算术类型 ...

  5. C++ Primer 第2章 变量和基本类型

    C++ Primer 第2章 变量和基本类型 C Primer 第2章 变量和基本类型 1 基本内置类型 算数类型 类型转换 字面值常量 2 变量 变量定义 3 复合类型 引用d左引用 指针d 4 c ...

  6. C++PRIMER第二章前半部分答案

    C++PRIMER第二章前半部分答案 哈哈哈,为什么是前半部分呢,后半部分还在学习中,重新系统性的学习c++,共同进步嘛,不多说,跟我一起来看看吧,第三章开始才是新手收割的时候,慢慢来~~ 2.1&a ...

  7. Java 第二章 变量

    第二章 变量 变量称为:是计算机语言中能储存计算机结果或能表示值抽象概念 .变量可以通过变量名访问 int money ; //变量 money=1000; //赋值 int money=1000: ...

  8. Java 第二章 变量、数据类型和运算符

    第二章      变量.数据类型和运算符 什么是变量: 变量代表一块内存区域,变量类型不一样,这一块内存的大小也不一样. #在编程语言里面,你可以通过定义变量,向内存里添加数据或者修改内存已有的数据. ...

  9. C++ Primer : 第二章:变量和基本类型(1)

    变量和基本类型之第一篇:基本内置类型和变量 一. (1) C++定义了一套包括算数类型和空类型,这些类型有:布尔类型bool,字符类型char,宽字符类型wchar_t,Unicode字符char16 ...

  10. C++primer第二章

    第二章 :变量和基本类型 2.1 基本内置类型 C++定义了一套包含算术类型(arithmetic type)和空类型(void)在内的基本数据类型 2.1.1 算术类型 算术类型的分类: 整型(in ...

随机推荐

  1. Windows活动目录_初识

    计算机组织形式 工作组(用户本地登录时构造SID进行权限分配): 域(统一身份验证与管理) 域注意事项 实体:域控.域用户.加入域的机子. 依赖的服务:netlogon服务 强制刷新组策略gpupda ...

  2. 齐博x1前台后台地址跳转的处理

    系统有三个入口,分别是 admin.php index.php member.php 所以就不能简单的使用TP默认的 url() 函数 而插件跟频道模块又有所不同,下面先讲解最基本的频道模块当中如何使 ...

  3. go-zero docker-compose搭建课件服务(四):生成Dockerfile

    0.转载 go-zero docker-compose 搭建课件服务(四):生成Dockerfile并在docker-compose中启动 0.1源码地址 https://github.com/liu ...

  4. day51-正则表达式02

    正则表达式02 5.4正则表达式语法02 5.4.6捕获分组 详见5.3.3 例子 package li.regexp; import java.util.regex.Matcher; import ...

  5. Dubbo 原理和机制详解 (非常全面)

    Dubbo 是一款Java RPC框架,致力于提供高性能的 RPC 远程服务调用方案.作为主流的微服务框架之一,Dubbo 为开发人员带来了非常多的便利. 大家好,我是 mikechen,专注分享「互 ...

  6. 驱动开发:内核监控Register注册表回调

    在笔者前一篇文章<驱动开发:内核枚举Registry注册表回调>中实现了对注册表的枚举,本章将实现对注册表的监控,不同于32位系统在64位系统中,微软为我们提供了两个针对注册表的专用内核监 ...

  7. Oracle中查询表结构的六种方法

    首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...

  8. JVM学习笔记——类加载和字节码技术篇

    JVM学习笔记--类加载和字节码技术篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的类加载和字节码技术部分 我们会分为以下几部分进行介绍: 类文件结构 字节码指令 编译期处理 类 ...

  9. 洛谷 P3201 梦幻布丁 题解

    (这篇题解可能没什么营养,主要是记录一下我用map乱搞启发式合并的神奇做法) 首先我们知道,我们肯定要用一堆集合维护每一种数当前的位置,并支持合并和数连续出现的段数两种操作 我发现这个东西并不好搞,但 ...

  10. Nginx负载均衡策略的介绍与调优

    工作中经常会用到nginx负载均衡这一块,下面对nginx负载均衡策略做个总结.本人在工作中最常用到的负载均衡策略是轮询策略. 在一般情况下,Web中间件最大的作用就是负责对请求进行分发,也就是我们常 ...