C++学习笔记2:变量和基本类型

补充C++基础笔记。

变量和基本类型

变量

1. 带符号类型和无符号类型不能混用。
如a=1, b=-1, 且a和b都是int,则表达式a * b的值为-1;如过此时a是int,b是unsigned类型,则结果须视当前机器上int所占位数而定(a转成unsigned后运算)。
2. 初始化赋值的区别:初始化的含义是创建变量时赋予其一个初始值,而赋值的含义时把对象的当前值擦除,而以一个新值来替代。
3. 对象:具有某种数据类型的内存空间。
定义于函数体内的内置类型的对象如果没有初始化,则其值未定义。类的对象如果没有显示地初始化,则其值则由类确定。
4. 变量的声明和定义:
声明:使得名字为程序所知 -> 规定了变量的类型和名字
extern int i; //声明i
定义:负责创建与名字关联的实体 -> 类型、名字、申请存储空间、可能会为变量赋一个初值
int j; //声明并定义了j
任何包含了显式初始化的声明即成为定义。
变量能且只能被定义一次,但是可以被多次声明 -> 多个文件使用同一个变量时,变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行说明,却绝对不能重复定义。
5. 变量命名规范
变量名一般用小写字母;自定义的类名以大写字母开头;多个单词中间有下划线_
6. 名字的作用域
作用域(scope)是程序的一部分,在其中名字有其特定的含义,C++中大多数作用域都以花括号分隔

复合类型:引用和指针 -> 更加复杂的声明符

1. 引用
引用并非对象,它只是为一个已经存在的对象所起的另外一个名字。

int ival = 1024;
int &refVal = ival; //refVal指向ival(是ival的另一个名字)
int &refVal2;   //报错:引用必须初始化

2. 指针
指针本身就是一个对象 -> 允许赋值和拷贝,生命周期内可以先后指向不同的对象;

1)指针无需再定义时赋初值。

double dp, *dp2;   //dp2是指向double型对象的指针,dp是double型对象

int ival = 42;
int *p = &val;   //这里的&为取地址符,p存放变量ival的地址,或者说p是指向变量ival的指针

double dval;
double *pd = &dval;   //正确:初始值是double型对象的地址
double *pd2 = pd;   //正确:初始值是指向double对象的指针

int *pi = pd;   //错误:指针pi的类型和pd的类型不匹配
pi = &dval;   //错误:试图把double型对象的地址赋给int型指针

2)指针的类型 <-> 指向对象的类型 ~ 要匹配

3)指针的四种状态:指向一个对象、指向紧邻对象所占空间的下一个位置、空指针(没有指向任何对象)、无效指针(其他情况)
指针指向一个对象 -> 解指针符*来访问该对象:

int ival = 42;
int *p = &ival;   //p指向变量ival
cout << *p;   //*p代表ival

4)空指针:不指向任何对象
生成空指针的办法 -> 空指针可以转换为任意其他的类型指针

int *p1 = nullptr;   //等价于int *p = 0;
int *p2 = 0;   //初始化为字面常量0
int *p3 = NULL;   //等价于int *p3 = 0; 这一操作需要首先#include cstdlib

//不可以直接将int变量赋值给指针
//建议:初始化所有指针

5)void指针:可以存放任何指针,但是不能直接操作void*指针所指的对象[不知道对象的类型,不知道能做什么操作]

6)指向指针的指针:

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

ppi和pi的关系
7)指向指针的引用:引用本身不是对象,因此不能定义指向引用的指针,但指针是对象,所以存在对指针的引用。

int i = 42;
int *p;   
int *&r = p;   //r是一个对指针p的引用

const 限定符

  1. 目的:使得变量的值不能被改变
const int i = get_size();   //正确:运行时初始化
const int j = 42;   //正确:编译时初始化->在编译过程中会把用到该变量的地方都替换成对应的值
const int k;   //错误:k是一个未经初始化的常量
  1. 如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。
    例子:extern const int bufSize = fcn();
  2. const的引用:不能修改其所引用的对象
int i = 42;
int &r1 = i;   //引用ri绑定对象i
const int &r2 = i;   //r2也绑定对象i,但是不允许通过r2修改i的值
//注:此时r2会随着i的变化而变化
r1 = 0;   //i的值修改为0
r2 = 0;   //错误:r2是一个常量引用
  1. 指针和const
    1)指向常量的指针(pointer to const)
    指向常量的指针不能用于改变其所指对象的值
const double pi = 3.14;
const double *cptr = &pi;
*cptr = 42;   //错误:不能给*cptr赋值

允许令一个指向常量的指针指向一个非常量对象(此时依然不能通过此指针改变所指对象的值)-> 特例

double dval  = 3.14;
cptr = &dval;   //正确:但是不能通过cptr改变dval的值

2)const指针(const pointer):将指针本身定义为常量 -> 存放在指针中的地址不能改变 -> 但指针指向的值可以改变

int errNumb = 0;
int *const curErr = &errNumb;   //curErr将一直指向errNumb
const double pi = 3.14159;
const double *const pip = &pi;   //pip是一个指向常量对象的常量指针
*curErr = 3;   //正确:const指针指向的值可以改变
*pip = 2.7;   //错误:指向常量的指针 指向的值不能通过指针改变

3)区分:底层(top-level)const和顶层(low-level)const
顶层const:对象本身是个常量
底层const:指针所指的对象是个常量

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

拷贝操作:顶层const不受影响,底层const的拷入拷出对象必须具有相同的底层const资格,或者两个对象的数据类型能够转换

i = ci;   //正确:ci是一个顶层const,对此操作无影响
p2 = p3;   //正确:p2和p3指向的对象类型相同,p3顶层const的部分不影响

int *p = p3;   //错误:p3包含底层const的定义,而p没有
p2 = &i;   //正确:int*能转换成const int*
int &r = ci;   //错误:普通的int&不能绑定到int常量上
const int &r2 = i;   //正确:const int&可以绑定到一个普通int上

4)constexpr和常量表达式 -> C++11新特性
声明为constexpr的变量一定是一个常量

constexpr int mf = 20;   //20是常量表达式
constexpr int limit = mf + 1;   //mf+1是常量表达式
constexpr int sz = size();   //只有当size是一个constexpr函数时才是一条正确的声明语句

指针和constexpr [constexpr将其所定义的对象置为了顶层const]

const int *p = nullptr;   //p是一个指向整型常量的指针
constexpr int *q = nullptr;   //q是一个指向整数的常量指针
constexpr int *np = nullptr;   //np是一个指向整数的常量指针,其值为空
int j = 0;
constexpr int i = 42;   //i的类型是整型常量
//i和j都必须定义在函数体外
constexpr const int *p = &i;   //p是常量指针,指向整数常量i
constexpr int *p1 = &j;   //p1是常量指针,指向整数j

处理类型

  1. 类型别名
    两种定义方式:关键字typedef和别名声明
typedef double wages; // wages是double的同义词

using SI = Sales_item;  //SI是Sales_item的同义词

typedef char *pstring;   //: 基本数据类型为指针
const pstring cstr = 0;   //cstr是指向char的常量指针
//不可以改写成const char *cstr -> 指向char常量的指针
const pstring *ps;   //ps是一个指针,对象是指向char的常量指针
  1. aoto类型说明符
    注意点:如果是常量引用/指针:auto一般会忽略掉顶层const,同时底层const则会保留下来。
int i = 0;
const int ci = i, &cr = ci;
const auto f = ci;   //ci的推演类型是int, f是const int

auto &g = ci;   //g是一个整型常量引用,绑定到ci
auto &h = 42;   //错误:不能为非常量引用绑定字面值
const auto &j = 42;   //正确:可以为常量引用绑定字面值

auto k = ci, &l = i;   //k是整数,l是整型引用 -> k的值可以改变
auto &n = i, *p2 = &ci;   //错误:i的类型是int而&ci的类型是const int
  1. decltype类型指示符
    decltype(f()) sum = x; //sum的类型就是函数f的返回类型
    注意点:
    1)decltype((variable))(注意是双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身就是一个引用时才是引用。
    2)如果i是int,则表达式i=x的类型是int&。

自定义数据结构

库类型string、istream、ostream等都是以类的形式定义的。

预处理器:确保头文件多次包含仍能安全工作的技术。
#include -> 预处理器看到#include标记时会用指定的头文件内容代替#include
#define指令把一个名字设定为预处理变量
#ifdef当且仅当变量已定义时为真
#ifndef当且仅当变量未定义时为真
检查结果为真:执行后续操作直到#endif

#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};
#endif
参考资料:
  1. C++ primer. 第五版.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值