C++primer 第二章变量和基本类型

C++primer 第二章变量和基本类型

2.2 变量

2.2.4名字作用域

#include <iostream>

int refused = 1000;

int main(int argc, char const *argv[])
{
    int unique = 0;
    //out_put#1, 输出refused和unique
    std::cout << refused << " " << unique << std:: endl;
    int refused = -1000;
    //output#2, 输出新建局部变量refused,新建的局部变量会覆盖之前的全局变量
    std :: cout << refused << " " << unique << std :: endl;
    //output#3n显示访问全局变量
    std::cout << ::refused << " " << unique << std::endl;
    return 0;
}

局部变量 refused 会覆盖全局变量 refused的值,在输出3中使用作用域操作符覆盖默认的作用域规则,使用作用域操作符像全局作用域发出请求获取作用域操作符右侧变量对应的名字。

2.3复合类型

2.3.1引用

引用相当于给对象起了另外一个名字,引用在定义的时候必须初始化,必须使用对象的名字给引用初始化,同时要保证引用和对象的数据类型都相同。初始化引用时不是将值拷贝给引用,而是将初始值和引用进行绑定,对引用进行修改相当于对对象进行修改。

int val = 1024;
int &reval = val;   //reval指向val
int &reval; //错误,引用在定义的时候必须初始化

reval = 2;  //相当于val = 2
int i = reval;  //相当于i = val

int &reval = 10;    //错误引用的初始值必须是一个对象
double dval = 3.14;
int &dreval = dval; //错误,引用要和对象的数据类型相同

2.4 const限定符

2.4.1 const 的引用

将引用绑定到 const 对象上,称之为对常量的引用,不能修改常量的引用。

const int ci = 1024;
const int &ri = ci; //正确,应用和其对象都是常量

ri = 42;    //错误,不能修改常量的引用
int &r2 = ci;   //错误,r2是非常量的引用不能去引用一个常量

int i = 42;
const int &r1 = i;  //正确,可以通过常量的引用去引用一个非常量
int &r2 = i;
r2 = 0; //正确,可以通过修改非常量的引用从而修改非常量的值
r1 = 0; //错误,不能修改常量引用
const int &r3 = r1 * 2;
int &r4 = r1 * 2;   //错误,r4是一个非常量的引用,r1是常量的引用

double dval = 3.14;
const int &ri = dval;   //正确
/*
*编译器执行的时候会生成一段临时对象 const int temp = dval
*const int &ri = temp;
*/

2.4.2 指针和 const

要想存放常量对象的地址,只能使用指向常量的指针

const double pi = 3.14;
double *ptr = pi;   //错误,ptr只是一个不同的指针
const double *ptr = &pi;    //正确
*ptr = 42.0;    //错误,不能给常量赋值

double dval = 3.1415926;
ptr = &dval;    //正确,可以改变指向常量的指针的指向但是不能改变ptr的值

const 指针
通过 const 设置常量指针,使指针始终指向一个对象,不能改变指针的指向

int errNumb = 0;
int *const curErr = &errNumb;   //curErr将一直指向errNumb
*curErr = 0;    //正确通过修改curErr的值来修改errNumb的值
const double pi = 3.14;
const double *const pip = &pi;  //pi是一个常量,指向常量的常量指针必须也是一个常量
*pip = 1592.6;  //错误,pip是一个指向常量的指针,不能修改
//pip是一个指向常量的常量指针,即不能修改其值,也不能修改它所指向的地址

const指针的语法形式:指针所指向的基本数据类型 *const 指针名 = 所指向的地址

2.4.3顶层 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
const int *const p3 = p2;   //右侧的是顶层const, 左侧的是底层const, 因为右侧的表示一个指针常量,左侧的const表示所指向的对象p2自身又是一个const

2.5处理类型

2.5.1 类型别名

typedef double wages;   //double 和 wages是同义词
typedef wages base, *p; //base是double的同义词,p是double*的同义词
using SI = Sales_Item;  //SI和Sales_Item是同义词

typedef char *pstring;
const pstring cstr = 0; //cstr是指向char的常量指针
const pstring *ps;  //ps是一个指针,对象是指向char的常量指针

//不能理解成一下形式
const char *cstr;   //这是一个cstr指针,其数据类型是char

2.5.3 decltype 类型指示符

使用 decltype 可以根据表达式的类型推导出要定义变量的类型,但是不使用表达式的值。
decltype(f()) sum = x; sum的类型和f()的返回值相同,编译器实际上并不调用f(),而是当调用f()的时候将f()的返回值类型作为sum的类型。

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是一个引用必须初始化

int i = 42, *p = &i, &r = i;
decltype(r + 0) b;  //正确;加法的结果是int,b的结果是一个int
decltype(*p) c; //错误,c是int &,必须初始化

decltype(r) 的结果是一个引用类型,可以把r作为表达式的一部分 decltype(r + 0) 的结果就是r所指的类型。
decltype((variable)) 的结果永远是一个引用类型,decltype(variable) 只有当variable是一个引用时结果才是引用。

decltype((r)) d;    //错误,d是一个引用类型必须初始化
decltype(r) e;  //e是一个int

posted on 2021-05-25 16:16  翔鸽  阅读(43)  评论(0编辑  收藏  举报