[C++ Primer] C++基础【1】

2021/11/10 17:13:35

本文主要是介绍[C++ Primer] C++基础【1】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

C++ Primer 中文版 (第5版)
电子工业出版社
C++ 11

文章目录

  • 第一章 开始
  • 第二章 变量和基本类型
    • 基本内置类型
    • 变量
    • 复合类型:引用和指针
    • const限定符
    • 处理类型
          • 复合类型、常量和auto
          • decltype类型指示符
          • decltype和引用
    • 自定义数据结构
          • 定义Sales_data类型
          • 预处理器概述

第一章 开始

  • 标准库iostream定义了4个IO对象:cin、cout、cerr(输出警告和错误)、clog(输出程序运行时的一般性信息,存入日志文件中);

  • std::cerr << "Error!" << std::endl;

  • std::cout << "Enter two numbers: " << std::endl; 输出运算符 <<左侧必须是一个iostream对象,右侧的运算对象是要打印的值,运算符将给定的值写到给定的iostream对象中,计算结果就是其左侧运算对象,返回左侧的运算对象,第一个运算符的结果成为第二个运算符的左侧运算对象;运算符endl被称为操纵符,写入endl的效果是结束当前行,并将设备关联的缓冲区中的内容刷到设备中;

  • 调试时,应该保证“一直”刷新流,否则如果程序崩溃,输出可能还在缓冲区,程序崩溃位置的推断可能是错的;

  • 读取输入数量不确定的输入数据,循环条件检测的是std::cin,检测流的状态。如果流是有效的,则检测成功,当遇到文件结束符(Windows系统中是ctrl + Z,然后按enter),或无效的输入(读入的值不是一个整数),istream对象的状态会变为无效:

int v = 0;
while (std::cin >> v){
	...
}
  • 成员函数有时也被称为方法;
  • python在程序运行时检查数据类型,C++是一种静态数据类型,类型检查发生在编译时;因此,编译器必须知道程序中每个变量对应的数据类型;

第二章 变量和基本类型

基本内置类型

  • 基本内置类型:算术类型(字符、整数、布尔值、浮点数)和空类型(void,不对应具体的值);

在这里插入图片描述

  • 计算机可寻址的最小内存快称为字节byte,由8 比特bit构成;

  • 存储的基本单元称为字word,通常由几个字节组成,由32或64bit构成;

  • 除bool型和扩展的字符型外,其他整型可以划分为有符号和无符号两种;

  • 无符号的仅能表示大于等于零的值;

  • 与其他整型不同,字符型被分为三种:char、signed char、unsigned char,但字符的表现形式只有两种:带符号和无符号的;

  • char会表现为带符号或无符号的,具体由编译器决定,不建议在算术表达式中使用char(可以指定signed char 或unsigned char);

  • 选择数据类型的经验准则:

  • 当明确知道数值不可能为负数时,选用无符号类型;

  • 算术表达式中,不要使用char 或 bool;

  • 浮点数选用double,float精度不够,但两者的计算代价差不多;

  • 类型转换:

  • 当给无符号类型赋值一个超出表示范围的值时,结果是对无符号类型表示数值总数取模后的余数;

  • 当给带符号类型赋值一个超出表示范围的值时,结果是未定义的,程序可能继续工作、崩溃、生成垃圾数据;
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 如果表达式中即有带符号的,也有无符号的,带符号数会自动转换为无符号数;

  • 字面值常量:

    • 默认情况下,十进制字面值是带符号的,八进制和十六进制字面值既可能带符号也可能是无符号的;
    • 十进制字面值类型是int、long、long long中能匹配的空间最小的那个,如果字面值连与之关联的最大的数据类型都放不下,将产生错误;

在这里插入图片描述
在这里插入图片描述

变量

  • int型数据初始化的几种方式:
    在这里插入图片描述

在这里插入图片描述

  • 定义于任何函数体之外的变量,默认初始化为0;

  • 定义于函数体内部的内置类型的变量将不被初始化;

  • 变量声明与定义:

  • 为了允许把程序拆分成多个逻辑部分来编写,C++支持将程序分割为若干个文件,每个文件单独编译;

  • 声明:使得名字为程序所知,一个文件如果想使用别处定义的名字,则必须包含对名字的声明;

  • 定义:创建与名字关联的实体,申请存储空间,并可能为变量赋初始值;

  • 任何包含显式初始化的声明,将成为定义,给extern标记的变量赋初始值,那就变成定义了;

  • 在函数体内部,如果试图初始化extern标记的变量,将引发错误;

  • 变量只能被定义一次(仅在一个文件中被定义),但是可以被多次声明;

extern int i;	// 声明i,不是定义i
int j;	// 声明并定义j
extern int k = 1;	// 定义
  • 标识符:

  • 由字母、数字、下划线构成,必须字母或下划线开头;

  • 长度没有限制,但是对大小写敏感;

  • C++为标准库保留了一些名字,自定义的标识符不能连续出现两个下划线,也不能以下划线紧连大写字母开头;

  • 定义在函数体外的标识符不能以下划线开头;

  • 变量名一般用小写字母,如index;

  • 类名一般以大写字母开头;

  • 作用域:

  • 大多数作用域以花括号分隔;

  • 名字的有效区域从名字的声明开始,以声明语句所在的作用域末端结束;

  • 作用域中一旦声明了某个名字,内层作用域都能访问该名字,同时允许内层作用域中重新定义外层作用域已有的名字;

在这里插入图片描述

  • 输出#3中,使用::来覆盖默认的作用域规则,因为全局作用域没有名字,所以当作用域操作符左侧为空时,获取全局作用域名字对应的变量;

复合类型:引用和指针

  • 引用(reference):左值引用、右值引用
  • 引用:为对象起了另外一个名字,定义引用时,程序把引用和初始值绑定在一起,而不是将初始值拷贝给引用;因为无法让引用绑定另一个对象,所以引用必须被初始化;
  • 引用不是对象,只是为已经存在的对象起另一个名字;
  • 因为引用本身不是一个对象,所以不能定义引用的引用;
  • 引用不是对象,没有实际地址,所以不能定义指向引用的指针;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 指针与引用的区别

    • 指针本身是一个对象,允许对指针赋值和拷贝,在指针的生命周期内可以先后指向几个不同的对象;
    • 指针无须在定义时赋初始值,但会指向一个不确定的值;

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

int ival = 42;
int *p = &ival;	// p存放着ival地址
cout << *p;	// 得到指针p所指的对象
*p = 0; // 经由p为ival赋值

在这里插入图片描述

  • NULL为预处理变量,预处理器是运行于编译之前的一段程序,当遇到预处理变量时,预处理器会自动将它替换为实际值;
  • 现在的C++最好使用nullptr,尽量避免使用NULL;

在这里插入图片描述
在这里插入图片描述

pi = &ival; // pi指向了ival
*pi = 0; // ival的值被改变,指针pi并没有变

在这里插入图片描述

  • 两个类型相同的指针,可以用==或!=比较,如果指针存放的地址相同,则他们相等;

  • 如果一个指针指向某对象,另一个指针指向另外对象的下一个地址,可能两个指针值相等;

  • void*指针:

  • 是一种特殊的指针类型,可以存放任意对象的地址,但存放的是什么类型的对象并不了解;

  • 不能直接操作void*指针所指的对象,因为不知道这个对象是什么类型;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 指向指针的指针 在这里插入图片描述

  • 指向指针的引用:

  • 引用本身不是一个对象,所以不存在指向引用的指针;

  • 指针是对象,所以存在对指针的引用;

  • 从右向左阅读r的定义,离变量名最近的符号是&,因此r是一个引用,*说明r引用的是一个指针;

在这里插入图片描述

const限定符

  • 创建后就不再改变,任何试图给常量赋值的行为都将引发错误;
  • const必须初始化;

在这里插入图片描述
在这里插入图片描述

  • ci的常量特征仅仅在执行改变ci操作时才会发挥作用;

  • 默认状态下,const对象仅在文件内有效,当多个文件中出现了同名的const变量,等同于在不同文件中分别定义了独立的变量;

  • const int a = 5; 编译器将在编译过程中把用到该变量的地方都替换为对应的值;

  • 某些时候,const变量的初始值不是常量表达式,且需要在文件间共享,只在一个文件中定义,在其他多个文件中声明并使用,解决的办法是:const变量不管是声明还是定义,都添加extern关键字;
    在这里插入图片描述

  • const的引用

  • 把引用绑定到const对象上,称之为对常量的引用;

在这里插入图片描述

  • 初始化和对const的引用
  • 初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型;
  • 允许为一个常量引用绑定非常量的对象、字面值、表达式;
    在这里插入图片描述
    在这里插入图片描述
  • 上图中,如果改成int &ri = dval;此时ri绑定的是临时量,该操作是非法的;

在这里插入图片描述

  • 指针和const
  • 指向常量的指针,不能用于改变其所指对象的值,但没有规定那个对象的值不能通过其他途径改变;

在这里插入图片描述
在这里插入图片描述

  • const指针
  • 常量指针,把指针本身定为常量,必须初始化,且它的值(存放在指针中的地址)不能再改变;
  • 从右向左阅读,离curErr最近的符号是const,说明curErr本身是一个常量对象,*表示curErr是一个指针;

在这里插入图片描述
在这里插入图片描述

  • 顶层const

  • 顶层const表示指针本身是个常量;

  • 底层const表示指针所指的对象是一个常量;

  • 执行对象的拷贝操作时,拷入和拷出的对象必须是具有相同的底层const资格,或者两个对象的数据类型必须能够转换(非常量可以转常量,反之不行);
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • constexpr和常量表达式

  • 常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式;

  • 字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式;
    在这里插入图片描述

  • constexpr变量

  • C++11中规定,允许将变量声明为constexpr类型,以便由编译器来验证变量的值是否是一个常量表达式;

  • 声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化;

  • constexpr函数:足够简单,编译时就可以计算其结果;
    在这里插入图片描述

  • 字面值类型

  • 包括算术类型、引用、指针这类简单、值也显而易见的,不包括自定义类、IO库、string等(不能被定义为constexpr);

  • 一个constexpr指针的初始值必须是nullptr或0,或者是存储于某个固定地址中的对象;

  • 函数体内定义的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量;

  • 相反的,定义于所有函数体之外的对象其地址固定不变,能用来初始化constexpr指针;

  • 允许函数定义一类有效范围超出函数本身的变量,这类变量和定义在函数体之外的变量一样有固定地址,因此constexpr引用能绑定到这样的变量上,constexpr指针也能指向这样的变量;

  • 指针和constexpr

  • 在constexpr声明中,如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关;
    在这里插入图片描述
    在这里插入图片描述

处理类型

  • 类型别名:是某种类型的同义词,用法同原类型;

  • 有两种方法定义类型别名:

    • 传统的方法是用关键字typedef

    • 新标准规定了新的方法,使用别名声明来定义,使用关键字using
      在这里插入图片描述
      在这里插入图片描述

    • 指针、常量和类型别名(太绕了,和直觉理解不一样……)
      在这里插入图片描述
      在这里插入图片描述

  • auto类型说明符

  • 把表达式的值赋值给变量时,让编译器通过初始值来推断表达式的类型;

  • auto定义的变量必须有初始值;

  • auto能在一条语句中声明多个变量,基本数据类型需要相同;
    在这里插入图片描述
    在这里插入图片描述

复合类型、常量和auto
  • 使用引用,其实是使用引用的对象,被用作初始化值时,真正参与初始化的其实是引用对象的值,编译器以引用对象的类型作为auto的类型;
    在这里插入图片描述

  • auto一般会忽略掉顶层const,底层const会保留下来;
    在这里插入图片描述

  • 还可以将引用的类型设为auto:

  • 在这里插入图片描述

在这里插入图片描述

decltype类型指示符
  • 有时会希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量,c++11引入了类型说明符decltype,作用是选择并返回操作数的数据类型;
  • 编译器分析表达并得到它的类型,却不实际调用函数或计算表达式的值;
  • 在这里插入图片描述
  • 在这里插入图片描述
decltype和引用
  • 在这里插入图片描述
  • 在这里插入图片描述

自定义数据结构

定义Sales_data类型

在这里插入图片描述

  • 类体右侧的表示结束必须后面加分号,因为类体后面可以紧跟变量名以表示对该类型的对象的定义;
  • 分号表示声明符的结束;
  • C++11规定,可以为数据成员提供一个类内初始值,用于初始化数据成员;
    在这里插入图片描述
预处理器概述
  • 确保头文件多次包含仍能安全工作的技术;
  • 预处理器是在编译之前执行的一段程序;
  • 头文件保护符,是一项预处理功能,依赖于预处理变量;预处理变量有两种状态:已定义和未定义;
  • #define指令把一个名字设定为预处理变量,#ifdef和#ifndef分别检查某个指定变量是否已经定义;
  • 预处理变量无视C++语言中关于作用域的规则;
  • 为了避免与程序中其他实体发生名字冲突,一般把预处理变量的名字全部大写;

在这里插入图片描述



这篇关于[C++ Primer] C++基础【1】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程