《C++Primer》第二章 变量和基本类型

2020-10-19  本文已影响0人  TOMOCAT

写这篇文章的目的

身为C++的零基础初学者,短期内把《C++Primer》啃下来是一个比较笨但是有效的方法,一方面可以掌握比较规范的C++语法(避免被项目中乱七八糟的风格带跑偏),另一方面又可以全面地了解C++语法以及C++11新标准(后续要做的事情就剩下查漏补缺,不断完善自己的知识体系)。

个人感觉从零学习一门新知识比较好的方法是快速了解知识的全貌,然后构建自己的知识地图,后续不断地补充相应的细节。

由于《C++Primer》和大多数的教科书一样废话连篇,因此想要精炼一下每篇文章的内容再打印成pdf,方便温故知新。

全文链接

基本内置类型

1. 内置类型的及其实现

2. 如何选择类型

3. 类型转换

// 切勿混用带符号类型和无符号类型
unsigned u = 10;
int i = -42;
std::cout << i + i << std::endl; // -84
std::cout << i + u << std::endl; // 如果int占32位则输出4294967264

4. 字面值常量literal

变量

1. 初始化

2. 变量声明与定义的关系

C++支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可独立编译。

为了支持分离式编译,C++将定义和声明区分开。其中声明规定了变量的类型和名字,定义除此功能外还会申请存储空间并可能为变量赋一个初始值。如果想声明一个变量而非定义它,就使用关键字extern并且不要显式地初始化变量:

变量能且仅能被定义一次,但是可以被多次声明。

extern int i; // 声明i而非定义i
extern int i = 1; // 定义i, 这样做抵消了extern的作用 

复合类型

1. 引用

C++11中新增了“右值引用”,而我们这里讲的引用指的是“左值引用”。

2. 指针

指针只可能是以下四种情况:

试图拷贝或者以其他方式访问无效指针的值都会引发错误,编译器并不会负责检查此类错误。空指针不指向任何对象,在试图使用一个指针之前最好先判断它是否为空。C++11中得到空指针最直接的方法就是字面值nullptr

建议:初始化所有指针。访问未经初始化的指针相当于去访问一个本不存在的位置上本不存在的对象。如果指针所占空间中恰好有内容,而这些内容又被当做某个地址。我们就很难分清它是否是合法的了。因此建议初始化所有指针,并且尽量等定义了对象之后再定义指向它的指针。如果实在不清楚指针应该指向何处,就将它初始化为nullptr,这样程序就能检测并在非法引用时报错。

const限定符

const对象一旦创建后其值就不能再改变,所以const对象必须初始化。

1. 多个文件共享const对象

如果想在多个文件之间共享const对象,那么必须在变量的定义之前添加extern关键字。

默认状况下,const对象仅在文件内有效。const int bufSize = 512;以编译时初始化的方式定义一个const对象时,编译器将在编译过程中把用到该变量的地方都替换成对应的值。如果我们希望只在一个文件中定义const然后在其他多个文件中声明并使用它。解决的方法是对于const变量无论是声明还是定义都使用extern关键字,这样就仅需定义一次了。

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

2. 常量引用

与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象。

const int c1 = 1024;
const int &r1 = c1;

3. 指针和const

int errNum = 0;
int *const curErr = &errNum; // curErr会一直指向errNum
const double pi = 3.14159;
const double *const pip = &pi; // pip是一个指向常量对象的常量指针

4. 顶层const

指针本身是一个对象,它又可以指向另一个对象。因此指针本身是不是常量以及指针所指的是不是一个常量就是两个相互独立的问题。顶层const表示指针本身是一个常量,底层const表示指针所指的对象是不是一个常量。

当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格。

5. constexpr和常量表达式

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

C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,且必须用常量表达式初始化。

处理类型

1. 类型别名

类型别名type alias是一个名字,它是某种类型的同义词。它让复杂的类型名字变得简单明了、易于理解和使用。

// 传统方法
typedef double wages; // wages是double的同义词
// 新标准
using SI = Sales_item

2. auto类型说明符

C++11引入了auto类型说明符,可以让编译器通过初始值来推断变量的类型。需要注意的是,编译器推断出来的auto类型有时候与初始值的类型并不完全一样,编译器会适当地改变结果类型使其更加符合初始化规则。

const int ci = i;
const auto f = ci;

自定义数据结构

1. 定义一个不带有任何运算功能的数据结构

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

Sales_data accum, trans, *salesptr;

2. 编写自己的头文件

为了确保各个文件中类的定义一致,类通常被定义在头文件中,而且类所在头文件的名字应与类的名字一样。

#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
上一篇 下一篇

猜你喜欢

热点阅读