C++ Primer 笔记三 变量
初始化
变量是命名的对象或引用,提供一个具名的、可供程序操作的存储空间。定义一个变量的基本形式是:首先是类型说明符,然后紧跟由逗号分隔的变量名组成的列表,最后以分号结束。
TYPE objlist;
int sum = 0, value; // 定义两个int型变量,同时为sum赋初值为0
在C++中,初始化和赋值是两个完全不同的操作。初始化时创建变量时赋予其一个初始值,变量一般都应该被初始化;而赋值是抹去对象当前值,以一个新值来替代。
如果定义变量时没有指定初值,则变量被默认初始化。定义于任何函数体之外的的变量被默认初始化为0。而定义在函数体内部的内置类型变量将不被初始化,其值是未定义的。类对象如果没有显式地初始化,则其值由类决定。
std::string g_str; // 默认初始化为空字符串
int g_int; // 默认初始化为0
int main() {
std::string local_str; // 默认初始化为空字符串,该行为由类决定
int local_int; // 不被初始化,其值是未定义的。
return 0;
}
声明和定义
C++是一种静态类型语音,即在编译阶段检查类型。静态类型检查要求编译器必须知道每一个实体对象的类型,因此变量必须在定义或声明后才能使用。
声明规定了变量的类型和名字;定义除了规定变量的类型和名字,还申请了存储空间,也可能会为变量赋初值。如果想声明一个变量而非定义它,就在变量名前添加关键字extern
,而且不要显式地初始化变量。任何包含显式初始化的声明即成为定义。
extern int i; // 声明i而非定义i
int j; // 声明并定义j;
extern double pi = 3.1416; // 声明并定义了pi,显式初始化为3.1416
变量只能被定义一次,但可以多次声明。在多个文件中使用同一个变量,必须将声明和定义分离,变量的定义有且只能出现在一个文件中,绝不可再其他文件中重复定义。
标识符
标识符即变量名,规定:
- 只能包含字母、数字和下划线,且必须以字母和下划线开头;
- 不能以C++保留字作为标识符;
- 用户自定义的标识符中不能连续出现两个下划线,也不能以下划线紧连大写字母开头;
- 定义在函数体外的标识符不能以下划线开头;
- 没有长度限制,但大小写敏感。
C++关键字 | |||||
---|---|---|---|---|---|
alignas | constexpr | extern | noexcept | static_assert | union |
alignof | const_cast | false | nullptr | static_cast | unsigned |
asm | continue | float | operator | struct | using |
auto | decltype | for | private | switch | virtual |
bool | default | friend | portected | template | void |
break | delete | goto | public | this | volatile |
case | do | if | rergister | thread_local | wchar_t |
catch | double | inline | reinterpret_cast | throw | while |
char | dynamic_cast | int | return | ture | |
char16_t | else | long | short | try | |
char32_t | enum | mutable | signed | typedef | |
class | explicit | namespace | sizeof | typeid | |
const | export | new | static | typename |
C++操作符替代名 | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
替代名 | and | bitand | compl | not_eq | or_eq | xor_eq | and_equ | bitor | not | or | xor |
操作符 | && | & | ~ | != | |= | ^ | &= | | | ! | || | ^= |
变量命名有很多约定俗成的规范,有助于提高代码的可读性,具体可参考《Google C++ 编程规范》第六章命名约定。
名字的作用域
C++中大多数作用域都以花括号分隔,同一个名字在不同的作用域中可能指向不同的实体。名字的有效区域始于名字声明处,结束于所在作用域的末端。
作用域可以包含彼此,被包含的作用域称为内层作用域,包含着别的作用域的作用域称为外层作用域。
作用域中声明的名字可以被它所嵌套的所有作用域访问,内层作用域若声明定义了与外层相同的名字,外层作用域中已存在的名字将被覆盖。使用作用域操作符(::
)可以访问被覆盖的外层作用域的名字。
// pro.cpp
#include <iostream>
// reuse拥有全局作用域
int reuse = 42;
int main() {
// unique拥有块作用域
int unique = 0;
std::cout << reuse << "\t" << unique << std::endl;
if (1) {
// inif 仅在 if 语句内有效
int inif = 33;
std::cout << ++unique << "\t" << inif << std::endl;
}
// 这里编译器会报错
// error: 'inif' was not declared in this scope.
//std::cout << inif << std::endl;
// 覆盖了全局变量reuse
double reuse = 3.14;
// 必须使用(::)显示访问外层作用域中相同的名字
std::cout << reuse << "\t" << ::reuse << std::endl;
return 0;
}
$ ./pro.out
42 0
1 33
3.14 42
一般来说,不宜定义于全局作用域同名的局部变量。