c++——变量和类型

上一章中展示的 “Hello World” 程序的有用性相当值得怀疑。我们必须编写几行代码,编译它们,然后执行生成的程序,只是为了获得写在屏幕上的简单句子的结果。我们自己输入输出句子肯定会快得多。

但是,编程不仅限于在屏幕上打印简单的文本。为了更进一步并能够编写执行真正节省我们工作的有用任务的程序,我们需要引入变量的概念。

想象一下,我让你记住数字 5,然后我让你同时记住数字 2。您刚刚在内存中存储了两个不同的值(5 和 2)。现在,如果我让你在我说的第一个数字上加 1,你应该在你的记忆中保留数字 6(即 5+1)和 2。然后,例如,我们可以减去这些值,得到 4 作为结果。

上面描述的整个过程是计算机可以用两个变量做什么的比喻。相同的过程可以用以下一组语句在 C++ 中表示:

1
2
3
4
a = 5;
b = 2;
a = a + 1;
result = a - b;

显然,这是一个非常简单的例子,因为我们只使用了两个小的整数值,但考虑到您的计算机可以同时存储数百万个这样的数字,并使用它们进行复杂的数学运算。

我们现在可以将 variable 定义为内存的一部分来存储一个值。

每个变量都需要一个名称来标识它并将其与其他变量区分开来。例如,在前面的代码中,变量名称是 、 、 和 ,但我们可以将变量命名为我们能想到的任何名称,只要它们是有效的 C++ 标识符即可。abresult

标识符

有效标识符是由一个或多个字母、数字或下划线字符 () 组成的序列。空格、标点符号和符号不能是标识符的一部分。此外,标识符应始终以字母开头。它们也可以以下划线字符 () 开头,但在大多数情况下,此类标识符被视为保留给特定于编译器的关键字或外部标识符,以及在任何位置包含两个连续下划线字符的标识符。在任何情况下,它们都不能以数字开头。

C++ 使用许多关键字来标识作和数据描述;因此,程序员创建的标识符无法匹配这些关键字。不能用于程序员创建的标识符的标准保留关键字是:

特定编译器也可能具有其他特定保留关键字。

非常重要:C++ 语言是一种“区分大小写”的语言。这意味着以大写字母书写的标识符不等同于另一个具有相同名称但以小写字母书写的标识符。因此,例如,变量与变量或变量不同。这是标识三个不同变量的三个不同标识符。__ alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq
RESULTresultResult

基本数据类型

变量的值以 0 和 1 的形式存储在计算机内存中的某个未指定位置。我们的程序不需要知道变量存储的确切位置;它可以简单地通过它的名称来引用它。程序需要注意的是变量中存储的数据类型。存储简单整数与存储字母或大浮点数不同;尽管它们都使用 0 和 1 表示,但它们的解释方式不同,而且在许多情况下,它们占用的内存量不同。

基本数据类型是由语言直接实现的基本类型,表示大多数系统本身支持的基本存储单元。它们主要可分为:

字符类型:它们可以表示单个字符,例如 或 。最基本的类型是 ,它是一个单字节字符。还为更广泛的字符提供了其他类型。'A''$'char
数值整数类型:它们可以存储整数值,例如 或 。它们以各种大小存在,可以是有符号的,也可以是无符号的,具体取决于它们是否支持负值。71024
浮点类型:它们可以表示具有不同精度级别的实值,例如 或 ,具体取决于使用三种浮点类型中的哪一种。3.140.01
布尔类型:布尔类型(在 C++ 中称为 )只能表示两种状态中的一种,即 。booltruefalse

以下是 C++ 中基本类型的完整列表:

类型名称* 关于尺寸/精度的说明
字符类型 char 大小正好是一个字节。至少 8 位。
char16_t 不小于 。至少 16 位。char
char32_t 不小于 。至少 32 位。char16_t
wchar_t 可以表示支持的最大字符集。
整数类型(有符号) signed char 大小与 相同。至少 8 位。char
signed short int 不小于 。至少 16 位。char
signed int 不小于 。至少 16 位。short
signed long int 不小于 。至少 32 位。int
signed long long int 不小于 。至少 64 位。long
整数类型(无符号) unsigned char (与签名的对应物大小相同)
unsigned short int
unsigned int
unsigned long int
unsigned long long int
浮点类型 float
double 精度不小于float
long double 精度不小于double
布尔类型 bool
空隙类型 void 无存储
空指针 decltype(nullptr)

* 某些整数类型的名称可以缩写,但不带 和 component – 只需要非斜体的部分来识别类型,斜体部分是可选的。即,可以缩写为 、 或 简称为 ;它们都标识相同的基本类型。

在上面的每个组中,类型之间的差异仅在于它们的大小(即它们在内存中占用多少):每个组中的第一个类型最小,最后一个类型最大,每种类型至少与同一组中前一种类型一样大。除此之外,组中的类型具有相同的属性。

请注意,在上面的面板中,除了 (大小正好为 1 字节) 之外,没有任何基本类型指定了标准大小 (但最多是最小大小)。因此,类型不是必需的(在许多情况下不是)这个最小大小。这并不意味着这些类型的大小未确定,而是所有编译器和计算机都没有标准大小;每个编译器实现都可以为这些类型指定最适合程序将要运行的体系结构的大小。这种相当通用的类型大小规范为 C++ 语言提供了很大的灵活性,使其能够在现在和将来的各种平台上以最佳方式工作。

上面的 type sizes 以 bits 表示;类型具有的位数越多,它可以表示的不同值就越多,但同时也会占用更多的内存空间:signedintsigned short intsigned shortshort intshortchar

大小 唯一可表示值 笔记
8 位 256 = 28
16 位 65 536 = 216
32 位 4 294 967 296 = 232 (~40 亿)
64 位 18 446 744 073 709 551 616 = 264 (~180 亿)

对于整数类型,具有更多可表示的值意味着它们可以表示的值范围更大;例如,一个 16 位无符号整数将能够表示 0 到 65535 范围内的 65536 个不同值,而其有符号整数在大多数情况下能够表示 -32768 到 32767 之间的值。请注意,与无符号类型相比,有符号类型的正值范围大约减少了一半,因为 16 位中的一位用于符号;这是一个相对适度的范围差异,并且很少能证明纯粹基于它们可以表示的正值范围来证明使用 unsigned 类型的合理性。

对于浮点类型,大小会影响其精度,因为其有效位和指数位或多或少。

如果类型的大小或精度不是一个问题,则通常选择 , , 和 来分别表示字符、整数和浮点值。它们各自组中的其他类型仅在非常特殊的情况下使用。

可以使用类获取特定系统和编译器实现中基本类型的属性(请参阅 standard header )。如果出于某种原因,需要特定大小的类型,则库会在 header 中定义某些固定大小的类型别名。

上述类型(字符、整数、浮点和布尔值)统称为算术类型。但是还存在另外两种基本类型: ,它标识缺少类型;和 type ,这是一种特殊类型的指针。这两种类型将在下一章中进一步讨论。

C++ 基于上面讨论的基本类型支持多种类型;这些其他类型称为复合数据类型,是 C++ 语言的主要优势之一。我们还将在以后的章节中更详细地介绍它们。charintdoublenumeric_limits"><limits>"><cstdint>voidnullptr

变量声明

C++ 是一种强类型语言,要求每个变量在首次使用之前都使用其类型进行声明。这会通知编译器在内存中为变量保留的大小以及如何解释其值。在 C++ 中声明新变量的语法很简单:我们只需编写类型,后跟变量名称(即其标识符)。例如:

1
2
int a;
float mynumber;

这是两个有效的变量声明。第一个变量声明一个 type 为 identifier 的变量。第二个变量声明一个 type 为 identifier 的变量。声明后,变量 and 可以在程序中其其余范围内使用。
如果声明多个相同类型的变量,则可以通过用逗号分隔它们的标识符在单个语句中声明它们。例如:intafloatmynumberamynumber

1
int a, b, c;

这声明了三个变量 (, 和 ),它们都是 类型,并且具有与以下完全相同的含义:abcint

1
2
3
int a;
int b;
int c;

要了解变量声明在程序中的实际效果,让我们看一下本章开头提出的关于您的心理记忆的示例的整个 C++ 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// operating with variables

#include <iostream>
using namespace std;

int main ()
{
  // declaring variables:
  int a, b;
  int result;

  // process:
  a = 5;
  b = 2;
  a = a + 1;
  result = a - b;

  // print out the result:
  cout << result;

  // terminate the program:
  return 0;
}
4

在 cpp.sh 上编辑和运行

如果除了变量声明本身之外的其他东西对你来说看起来有点奇怪,请不要担心。其中大部分将在接下来的章节中更详细地解释。

变量的初始化

当上面示例中的变量被声明时,它们具有未确定的值,直到第一次为它们分配一个值。但是,变量从声明的那一刻起就可能具有特定值。这称为变量的初始化

在 C++ 中,有三种方法可以初始化变量。它们都是等价的,让人想起该语言多年来的演变:

第一个,称为类似 c 的初始化(因为它继承自 C 语言),包括附加一个等号,后跟变量初始化的值:

例如,要声明一个 called 类型的变量,并从声明的同一时刻开始将其初始化为零, 我们可以写:type identifier = initial_value;intx

1
int x = 0;

第二种方法称为构造函数初始化(由 C++ 语言引入),将初始值括在括号 () 之间:

例如:()type identifier (initial_value);

1
int x (0);

最后,第三种方法,称为统一初始化,与上述方法类似,但使用大括号 () 而不是括号(这是由 2011 年的 C++ 标准修订版引入的):

例如:{}type identifier {initial_value};

1
int x {0};

初始化变量的所有三种方法在 C++ 中都是有效且等效的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// initialization of variables

#include <iostream>
using namespace std;

int main ()
{
  int a=5;               // initial value: 5
  int b(3);              // initial value: 3
  int c{2};              // initial value: 2
  int result;            // initial value undetermined

  a = a + b;
  result = a - c;
  cout << result;

  return 0;
}
6

在 cpp.sh 上编辑和运行

类型推导:auto 和 decltype

初始化新变量时,编译器可以由初始值设定项自动确定变量的类型。为此,用作变量的类型说明符就足够了:auto

1
2
int foo = 0;
auto bar = foo;  // the same as: int bar = foo; 

此处,声明为具有类型;因此,type of 是用于初始化它的值的类型:在本例中,它使用 的类型 ,即 。

未初始化的变量也可以使用带有说明符的 type deduction:barautobarfoointdecltype

1
2
int foo = 0;
decltype(foo) bar;  // the same as: int bar; 

此处,被声明为与 .

并且是最近添加到该语言中的强大功能。但是,它们引入的类型推导功能旨在当类型无法通过其他方式获取类型时,或者使用它可以提高代码可读性时使用。上面的两个例子可能都不是这些用例。事实上,它们可能降低了可读性,因为在阅读代码时,必须搜索 的类型 才能真正知道 的类型。barfooautodecltypefoobar

字符串简介

基本类型表示由可以运行代码的计算机处理的最基本类型。但 C++ 语言的主要优势之一是其丰富的复合类型集,其中基本类型只是构建块。

复合类型的一个示例是 class.这种类型的变量能够存储字符序列,例如单词或句子。一个非常有用的功能!

与基本数据类型的第一个区别是,为了声明和使用此类型的对象 (变量),程序需要在 standard library (header) 中定义类型的地方包含 Headers :string<string>


// my first string
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string mystring;
  mystring = "This is a string";
  cout << mystring;
  return 0;
}
This is a string

在 cpp.sh 上编辑和运行

如前面的示例所示,字符串可以使用任何有效的字符串文本进行初始化,就像数字类型变量可以初始化为任何有效的数字文本一样。与基本类型一样,所有初始化格式都对字符串有效:

1
2
3
string mystring = "This is a string";
string mystring ("This is a string");
string mystring {"This is a string"};

字符串还可以执行基本数据类型可以执行的所有其他基本作,例如在没有初始值的情况下声明,并在执行过程中更改其值:


// my first string
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string mystring;
  mystring = "This is the initial string content";
  cout << mystring << endl;
  mystring = "This is a different string content";
  cout << mystring << endl;
  return 0;
}
This is the initial string content
This is a different string content

在 cpp.sh 上编辑和运行

注意:插入纵器结束 line (打印换行符并刷新流)。

该类是复合类型。正如你在上面的例子中看到的,复合类型的使用方式与基本类型相同:使用相同的语法来声明变量和初始化它们。

有关标准 C++ 字符串的更多详细信息,请参阅类参考。endlstringstring

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容