欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++ primer 第五版----学习笔记(二)

程序员文章站 2022-06-11 21:34:05
...

1.算术类型:字符、整型数、布尔值和浮点数;c++标准规定的尺寸的最小值:

c++ primer 第五版----学习笔记(二)

  • c++语言规定一个int至少和一个short一样大,一个long long至少和一个long一样大。其中数据类型long long实在c++11中新定义的。
  • 带符号类型(signed),无符号类型(unsigned);在带符号类型名前添加unsigned就能得到无符号类型。
  • 如何选择类型:(1)当明确知晓数值不可能为负时,选用无符号类型。
  •                          (2)使用int执行整数运算。
  •                          (3)在算术表达式中不要使用char或bool,只有在存放字符或布尔值时才使用它们。
  •                          (4)执行浮点数运算选用double。

2.类型转换(部分重点):

  • 赋给无符号类型一个超出其表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。例如:8比特大小的unsigned char 可以表示0至255区间内的值,如果我们赋了一个区间以外的值,则实际的结果是该值对256取模后所得的余数。因此,把-1赋給8比特大小的unsigned char 所得的结果是255.
  • 当我们赋給带符号类型一个超出它表示范围的值时,结果时未定义的(undefined)。此时,程序可能继续工作、可能崩溃,也可能生成垃圾数据。

3.含有无符号类型的表达式:

//1.当表达式中既出现无符号数又有int值时,int值会转换成无符号数
unsigned u = 10;
int i = -42;
cout << i + i << endl;//输出-84
cout << i + u << endl;//如果int占32位,输出4294967264

//2.从无符号数减去一个值,无论该值是不是无符号数,都要确保不能为负值
unsigned u1 = 42, u2 = 10;
cout << u1 - u2 << endl;//输出32
cout << u2 - u1 << endl;//结果是取模后的值

//3.当使用无符号数作为循环变量时,注意循环控制条件

4.字面值常量(对应一种数据类型,字面值常量的形式和值决定了它的数据类型):

  • 整型和浮点型字面值:形如42、20(整型字面值),3.141519(字符型字面值)
  • 字符和字符串字面值:形如'a'(字符字面值),"hello world"(字符串字面值)
  • 转义序列(均以反斜线作为开始):
//转义序列
//  换行符\n       横向制表符\t     报警(响铃)符\a
//  纵向制表符\v    退格符\b        双引号\"
//  反斜线\\       问号\?           单引号\'
//  回车符\r       进纸符\f

cout << '\n';//转到新一行
cout << "\tHi!\n";输出一个制表符,输出"Hi!",转到新一行

//泛化转义序列示例
//  \7(响铃)   \12(换行符)  \40(空格符)
//  \0(空字符)  \115(字符M)  \x4d(字符M)

cout << '\115' << '\n';//输出M,转到新一行
  
  • 指定字面值类型(通过添加下表的前缀和后缀,可以改变字面值的类型): 

c++ primer 第五版----学习笔记(二)

 

 

 

 

 

 

 

 

  •  布尔字面值和指针字面值:true和false(布尔字面值),nullptr(指针字面值)

5.变量初始化(对象获得一个特定的值):

  • 初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值查擦除,以一个新值替代
  • 列表初始化:用花括号来初始化变量,形如 int  units_sold{0};
  • 默认初始化:如果定义变量时没有指定初值,则变量被默认初始化

6.extern关键字:

//如果想声明一个变量而非定义它,就在变量前添加关键字extern

extern int i;  //声明i而非定义i
int j;         //声明并定义j

//extern语句如果包含初始值就不再是声明而是定义

extern double pi = 3.1416;  //定义

7.如果函数有可能用到某全局变量,则不宜再定义一个同名的局部变量

int i = 42;
int main()
{
    int i = 100;
    int j = i;
}
//程序中j的值为100,定义在外部的全局变量被同名局部变量覆盖

8.复合类型:引用和指针

(1)引用

  • 定义引用时,程序将引用和它的初始值绑定在一起
  • 引用并非对象(所以不能定义引用的引用),它只是为一个已经存在的对象所起的另外一个名字
  • 引用只能绑定对象,而不能与字面值或某个表达式的计算结果绑定在一起
int ival = 1024;
int &refval = ival;        //refval指向ival(是ival的另一个名字)
int &refval2;              //报错:引用必须被初始化

int refval4 = 10;          //错误:引用类型的初始值必须是一个对象 
double dval = 3.14;
int &refval5 = dval;       //错误:引用的类型要与绑定的对象一致

(2)指针

  • 指针本身是一个对象,允许对指针拷贝和赋值
  • 指针无须在定义时赋初值
  • 指针的类型与所指对象的类型要匹配
  • 使用nullptr初始化指针,得到空指针(0或null也可以初始化指针,但常用nullptr)
  • void *指针:一种特殊的指针类型,可以存放任意对象的地址
  • 指向指针的指针、指向指针的引用
int ival = 42;
int *p = &ival;          //p存放变量ival的地址,或者说p是指向变量ival的指针


int *p1 = nullptr;       //使用nullptr初始化指针

double obj = 3.14, *pd = &obj;
void *pv = &obj;         //obj可以是任意类型的对象
pv = pd;                 //pv可以存放任意类型的指针

int ival = 1024;
int *pi = &ival;         //pi指向一个int型的数
int **ppi = &pi;         //ppi指向一个int型的指针

int i = 42;
int *p;
int *&r = p;             //r是一个对指针p的引用
r = &i;                  //r引用了一个指针,因此给r赋值&i就是令p指向i

9.const限定符

  • const对象创建后其值不能改变,所以const对象必须初始化,初始值可以是任意复杂的表达式
  • 默认状态下,const对象只在文件内有效,不能多个文件共享;如果想在多个文件之间共享const对象,须在变量定义之前添加extern关键字
  • const的引用,若引用绑定在const对象上,则称之为对常量的引用,对常量的引用不能被用作修改它所绑定的值
  • 允许为一个常量引用绑定非常量的对象、字面值或一般表达式
  • 指向常量的指针不能用于改变其所指对象的值;只能使用指向常量的指针存放常量的地址;常量指针必须初始化
  • 顶层const表示指针本身是一个常量(任意的对象是常量),底层const表示指针所指的对象是一个常量
const int i = 42;
const int j;                //错误:const常量必须初始化

//file_1.cc定义并初始化了一个常量,该常量能被其它文件访问
extern const int bufsize = fun();
//file_1.h头文件
extern const int bufsize;   //与file_1.cc中定义的bufsize是同一个

const int ci = 1024;
const int &r1 = ci;         
r1 = 42;                    //错误:r1是对常量的引用
int &r2 = ci;               //错误:试图让一个非常量引用指向一个常量对象

const double pi = 3.14;
double *ptr = &pi;          //错误:ptr是一个普通指针
const double *cptr = &pi;   //正确:cptr可以指向一个双精度常量
*cptr = 42;                 //错误:不能给*cptr赋值

const double pi = 3.14159;
const double *const pip = &pi;//pip是一个指向常量对象的常量指针

10.constexpr和常量表达式

  • 常量表达式:指值不会改变并且在编译过程就能得到计算结果的表达式
  • c++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式
  • 一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象
const int max_files = 20;         //max_files是一个常量表达式
cosnt int limit = max_files + 1;  //limit是一个常量表达式

constexpr int mf = 20;            //20是常量表达式
constexpr int limit = mf + 1;     //mf + 1是常量表达式

constexpr int *q = nullptr;       //q是一个指向整数的常量指针

11.处理类型:类型别名、auto类型说明符,decltype类型指示符

  • 类型别名:使用关键字typedef、using来定义类型的别名
  • auto类型说明符:让编译器通过初始值来推算变量的类型
  • decltype类型指示符:选择并返回操作数的数据类型
typedef double wages;      //wages是double的同义词
using SI = Sales_item;     //SI是Sales_item的同义词

//auto声明语句只能有一种基本数据类型
auto i = 0, *p = &i;       //i是整数、p是整型指针
auto sz = 0, pi = 3.14;    //错误:sz和pi的类型不一致

auto &h = 42;              //错误:不能为非常量引用绑定字面值
const auto &j = 42;        //正确:可以为常量引用绑定字面值

decltype(f()) sum = x;     //sum的类型就是函数f的返回类型
int  i = 42;
decltype((i)) d;           //错误:d是int&,必须初始化
decltype(i) e;            //正确:e是一个未初始化的int
//切记:decltype((variable))的结果永远是引用,而decltype(variable)的结果只有当variable本身是一个引用时才是引用。

12.部分习题解答:

2.1:

short和int至少16位,long至少32位,long long至少64位;无符号类型只能表示大于0的数,有符号则能表示正数、负数和0;float精度低,double精度高

2.5、2.7、2.8:

熟悉转义序列以及指定字面值类型

2.10:

string global_str;   //初值为空字符串
int global_int;     //初值为0
int main()
{
    int local_int; //初值不确定
    string local_str;  //初值为空字符串
}

2.17:

int i, &ri = i;
i = 5; ri = 10;     //首先将i赋值为5,通过指针将i的值改为10
cout << i << " " << ri << endl;  //输出结果10 10

2.18:

#include <iostream>
using namespace std;
int main()
{
    int a = 0, b = 1;
    int *pi = &a, *pv = pi;
    pi = &b;  //改变了指针的值
    *pv =b;   //改变了指针所指对象的值
    return 0;
}

2.23:

不能,指针是否有效还未知!!

2.27:

(a)引用r的赋值对象必须是一个对象,不合法

(b)合法,将p2设置为常量指针,初始化为i2对象的地址

(c)合法,将i设置为常量,r设置为常量的引用(const int &r = 0正确,而int &r = 0不正确)

(d)合法,p3为指向常量的常量指针,初始值为i2的地址

(e)合法,p1为指向常量的指针,初始值为i2的地址

(f)使用不合法

(g)合法,正常赋值

2.30:

v2是顶层const;p2是底层const;p3最左是底层,右边是顶层const

其他都不是const

2.31:

顶层const拷贝不受限制,但是底层const的拷贝对象必须具有相同的底层const资格。

2.36:

a是int类型 4

b是int类型 4

c是int类型 4

d是int &类型 4

2.39:

[error] expected ';' after struct definition

2.41、2.42:

//Sales_data.h
struct Sales_data {
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

//Sales_data.cpp
#include<iostream>
#include<string>
#include "Sales_data.h"
using namespace std;

int main()
{
	Sales_data data1, data2;
	double price ;
	cin >> data1.bookNo >> data1.units_sold >> price;
	data1.revenue = data1.units_sold * price;
	cin >> data2.bookNo >> data2.units_sold >> price;
	data2.revenue = data2.units_sold * price;
	if (data1.bookNo == data2.bookNo)
	{
		unsigned totalcnt = data1.units_sold + data2.units_sold;
		double totalrevenue = data1.revenue + data2.revenue;
		cout << data1.bookNo << " " << totalcnt << " " << totalrevenue << " ";
		if (totalcnt != 0)
		{
			cout << totalrevenue / totalcnt << endl;
		}
		else
		{
			cout << " (no sales) " << endl;
		}
		system("pause");
		return 0;
	}
	else
	{
		cout << "Data must refer to the same ISBN" << endl;
	}
	system("pause");
    return 0;
}

 

相关标签: c