变量和 auto
程序要记住一些东西:考试的分数、商品的价格、顾客的名字。变量就是一个有名字的格子,里面放一个值。在 C++ 里,用变量之前要说清楚两件事:它叫什么,放的是哪种值。
1#include <iostream>2 3int main() {4 int score = 90;5 std::cout << "分数:" << score << '\n';6 return 0;7}
分数:90
int score = 90; 的意思是:要一个放整数(int)的格子,名字叫 score,先放进 90。std::cout << score 显示的是格子里的值,不是 score 这几个字母。
行尾的 '\n' 用的是单引号:它是一个字符,和 "\n" 一样会换行。下面马上会讲字符。
声明和赋值
int stock; 是声明变量:告诉编译器有这么一个变量,它放整数。stock = 12; 是赋值:往格子里放一个值。两步可以分开写,也可以像上面那样合成一行。
1#include <iostream>2 3int main() {4 int stock;5 stock = 12;6 std::cout << "库存:" << stock << '\n';7 stock = 7;8 std::cout << "库存:" << stock << '\n';9 return 0;10}
库存:12 库存:7
赋值可以做很多次,新值换掉旧值。C++ 里的 = 不是「等于」,而是「把右边的值放进左边的变量」。点单步,看 stock 怎么从 12 变成 7。
这段程序显示什么?
1#include <iostream>2 3int main() {4 int a = 5;5 int b = a;6 a = 9;7 std::cout << b << '\n';8 return 0;9}
int b = a; 把 a 当时的值 5 抄了一份放进 b。后来 a 换成 9,b 里的 5 不会跟着变。
几种基本类型
每个变量都有固定的类型,声明时写在名字前面,以后不能改。先认识最常用的五种:
| 类型 | 放什么 | 例子 |
|---|---|---|
int | 整数 | 90、-3、0 |
double | 带小数点的数 | 4.5、-0.25 |
char | 一个字符,写在单引号里 | 'A'、'7'、'\n' |
bool | 真或假 | true、false |
std::string | 一串文字,写在双引号里 | "小林"、"苹果" |
std::string 也来自标准库,要 #include <string>。一条 cout 语句可以连着显示好几个变量:
1#include <iostream>2#include <string>3 4int main() {5 std::string name = "小林";6 int count = 3;7 double price = 4.5;8 char size = 'M';9 bool paid = true;10 std::cout << name << " 买了 " << count << " 件,单价 " << price << '\n';11 std::cout << "尺码:" << size << ",已付款:" << paid << '\n';12 return 0;13}
小林 买了 3 件,单价 4.5 尺码:M,已付款:1
cout 显示 double 时不会补多余的 0,4.5 就显示 4.5。bool 显示成 1(真)或 0(假);想显示成 true / false 怎么写,第 6 课讲。char 一次只放一个英文字母、数字或符号,汉字要放进 std::string。
先赋值,再使用
声明了变量却没给它值,格子里是什么?C++ 不管:里面可能是任何数,这次和下次还可能不一样。用这样的值是未定义行为。在普通的电脑上,程序会照样跑下去,显示一个莫名其妙的数。我们的引擎会停在出事的那一行,告诉你是哪个变量:
1#include <iostream>2 3int main() {4 int total;5 std::cout << "总数:" << total << '\n';6 return 0;7}
总数:
use of uninitialized value发生了什么: 停在第 5 行:「total」还没有赋值就被用了。真的 C++ 里这会是一个乱数(每次运行都可能不一样)。
改法很简单:声明的时候就给它一个值,比如 int total = 0;。std::string 不一样:不给值,它就是一个空字符串 "",可以放心用。
小技巧: 声明 int、double 这些变量时顺手给它一个值,就不会犯这个错。
常量 const
有些值定下来就不该再变,比如一周的天数。声明时在前面加 const,它就成了常量;以后谁想改它,编译器都不答应:
1#include <iostream>2 3int main() {4 const int DAYS_IN_WEEK = 7;5 std::cout << "一周有 " << DAYS_IN_WEEK << " 天\n";6 DAYS_IN_WEEK = 8;7 return 0;8}
main.cpp: In function 'int main()':
main.cpp:6:18: error: assignment of read-only variable 'DAYS_IN_WEEK'
6 | DAYS_IN_WEEK = 8;
| ~~~~~~~~~~~~~^~~read-only variable 是「只读的变量」:只能读,不能改。常量常用大写字母和下划线起名,一眼就能和普通变量分开。去掉最后那次赋值,程序就能运行了。
auto:让编译器推出类型
写 auto 代替类型,编译器会看 = 右边的值,推出变量是什么类型:
1#include <iostream>2 3int main() {4 auto count = 3;5 auto price = 4.5;6 auto grade = 'A';7 auto total = price * count;8 std::cout << count << " " << price << " " << grade << " " << total << '\n';9 return 0;10}
3 4.5 A 13.5
3 是整数,所以 count 是 int;4.5 带小数点,price 是 double;'A' 是字符,grade 是 char;price * count 的结果是 double,total 也是。点单步,看每个变量出现时的值。
auto 不是「什么都能放」:类型在声明的那一刻就定死了。
这段程序显示什么?
1#include <iostream>2 3int main() {4 auto people = 3;5 people = 3.9;6 std::cout << people << '\n';7 return 0;8}
auto people = 3; 让 people 成了 int。后来放进 3.9 时,小数部分直接丢掉(不会四舍五入),所以是 3。
int、double 这种短类型,这门课照样写出来,读起来更清楚。以后遇到很长的类型名,auto 就很省事了。
注意: auto name = "小林"; 推出来的不是 std::string,而是 C 风格的字符串。要字符串,就写 std::string name = "小林";。
花括号初始化
给变量初始值还有一种写法:把值放在花括号里,int score{90};。它和 = 90 的结果一样,但多了一道检查:值放不进去,编译器就报错,而不是悄悄丢掉一部分。
1#include <iostream>2 3int main() {4 int people{3.9};5 std::cout << people << '\n';6 return 0;7}
main.cpp: In function 'int main()':
main.cpp:4:16: error: narrowing conversion of '3.8999999999999999e+0' from 'double' to 'int' [-Wnarrowing]
4 | int people{3.9};
| ^~~narrowing conversion 是「变窄的转换」:double 的 3.9 放进 int 要丢掉小数,花括号不允许。(报错里的 3.8999999999999999e+0 就是 3.9:大多数小数在电脑里存得不完全准。)这门课里,普通变量用 =;后面讲 std::vector 这类容器时会用到花括号。
起名的规矩
变量名由字母、数字和下划线 _ 组成,还有几条规矩:
| 规矩 | 可以 | 不行 |
|---|---|---|
只用字母、数字和 _ | total_price | total-price |
| 不能以数字开头 | day2 | 2day |
| 不能有空格 | max_score | max score |
| 不能用 C++ 自己的词 | count | int |
大写和小写是不同的字母,score 和 Score 是两个变量:
1#include <iostream>2 3int main() {4 int score = 90;5 int Score = 60;6 std::cout << score << " 和 " << Score << '\n';7 return 0;8}
90 和 60
能这么写,不代表应该这么写:两个名字只差大小写,很容易看错。名字要说清楚它放的是什么:price 比 p 好,max_score 比 ms 好。
练一练
写好代码,点检查。提示随便看,实在想不出来再看答案。
一件商品
✓声明三个变量:std::string 的 name 是 "牛奶",double 的 price 是 6.5,int 的 stock 是 20。用它们显示 牛奶:6.5 元,还剩 20 瓶。
牛奶:6.5 元,还剩 20 瓶
1#include <iostream>2#include <string>3 4int main() {5 6 return 0;7}
用 auto 算总价
✓用 auto 声明 total,值是 price * count,然后显示 总价:13。
总价:13
1#include <iostream>2 3int main() {4 double price = 6.5;5 int count = 2;6 7 return 0;8}
修好它:放不进去的价格
✓这段程序编译不过。改好它,让它显示 价格:19.9。
价格:19.9
1#include <iostream>2 3int main() {4 int price{19.9};5 std::cout << "价格:" << price << '\n';6 return 0;7}
这一课学会了
- 变量先声明再用:
int stock;声明,stock = 12;赋值,也可以合成int stock = 12;。 =是把右边的值放进左边的变量;再赋值,新值换掉旧值。int放整数,double放小数,char放一个字符,bool放真假,std::string放一串文字。- 一条
cout语句用几个<<就能连着显示几样;bool显示成 1 或 0。 - 用没赋过值的
int是未定义行为;声明时就给它一个值。 const让变量变成常量,改它会编译错误。auto让编译器从右边的值推出类型,类型推出来就固定了。- 花括号初始化
int n{3};不允许变窄,int n{3.5}编译错误。 - 名字用字母、数字和
_,不以数字开头,不用 C++ 自己的词,大小写不同。