认识 C Plus Plus
本篇主要由C++中文学习网学习而来,其中包括其他途径和自学编写而成。
std::是什么
提示
在 c++中std::是个命名空间标识符,在C++标准库中的函数或者对象都是在命名空间 std 中定义的,所以我们使用std``Visio Studio就会明白我们调用的函数或者对象是命名空间中的。
什么时候使用 std::,什么时候不用?
一般来说,建议使用std::
如果使用非标准库文件,不用写
不过作为一个新手,不妄自菲薄,还是老老实实按标准规则来
什么是 C++标准库
C++标准库C++ Standard Library。是类库和函数的集合,其使用核心语言写成,由 C++标准委员会制定,并不断维护。
C++标准库又分为标准函数库和面向对象类库。
标准函数库
包括:输入/输出 I/O、字符串、数学、时间、日期和本地化、动态分配、其他、宽字符函数等
面向对象类库
包括:标准的 C++ I/O 类、数值类、STL 容器类、STL 算法、STL 函数对象、STL 迭代器、STL 分配器、本地化库、异常处理类、杂项支持库。
开始
变量初始化和赋值
初始化有默认初始化、拷贝初始化、直接初始化等
#include <iostream>
int main()
{
// std是iostream库中的功能 - 需要安装导入iostream
// 双斜杠可以进行单行注释
//int a; // 可以将注释写在语句后面
/*
* 进行多行注释
* 多行注释不能嵌套,多行注释中不能嵌套多行注释
*/
// 注释是一个好习惯
std::cout << "Hello World!\n";
// 初始化和赋值
// 初始化
int a; //默认初始化
int b = 2;//拷贝初始化 - 拷贝赋值
int c(6);//直接初始化 - 直接将6设置给c
a = 1; // 将1拷贝赋值给a
// 拷贝赋值效率低于其他赋值
// C++11引入了列表初始化
int d{ 3 };//直接列表初始化
int e = { 4 };//拷贝列表初始化
int f{};//值列表初始化 - 输出0
std::cout << a;
std::cout << b;
std::cout << d;
std::cout << e;
std::cout << f;
std::cout << c;
}注意
默认初始化是大多数计算机语言所常用的一种赋值方式,但在 C++中,这是一种稍显效率低的一种赋值方式。在 C++中默认初始化效率低于其他初始化
std::endl - 结束符/换行符
std::cout << "Hello";
std::cout << "World";
》 HelloWorld
std::cout << "Hello" << std::endl;
std::cout << "World" << std::endl;
》 Hello
》 World'\n - 换行符'
std::cout << "Hello";
std::cout << "World";
》 HelloWorld
std::cout << "Hello" << '\n';
std::cout << "World" << '\n';
》 Hello
》 World区别:
用std::endl表示将光标移动到下一行,并刷新缓冲区。
用\n是将光标移动到下一行而不刷新缓冲区
可以看出相对于std::endl来说\n更显高效
std::cin - 获取键盘输入
目前大家都知道通过使用std::cout可以输出到控制台信息,那么如何获取控制台输入的信息呢?
#include <iostream>
int main() {
int a{};
std::cin >> a;
std::cout << "a = " << a << std::endl;
return 0;
}执行命令会发现,控制台让我们输入,输入完成后就会输出我们输入的值
通过以上操作我们知道std::cin语句可以获取输入信息
未初始化的变量
在 C++中,系统不会自动给初始化变量赋值,因此,当变量被分配到内存地址来存储数据时,该变量 的默认值可能是内存地址中已经存在的任何(垃圾)值!
尚未给定值的变量成为未初始化变量。
不过若出现未初始化变量时,程序会捕获到错误error C4700: 使用了未初始化的局部变量...
#include <iostream>
int main() {
int x;
std::cout << x;
return 0;
}error C4700: 使用了未初始化的局部变量“x”如果要避免上述报错,一定要运行
使用技巧骗过编辑器
#include <iostream>
void doNothing(int&) {
// 暂时不需要理解&的用途,让编辑器理解变量已被使用
}
int main() {
int x;
doNothing(x);//让编辑器认为x会被写入数据
std::cout << x;//结果是未知的
return 0;
}警告
使用未初始化变量是一个很严重的问题!
扼要重述:
- 初始化=在定义点为对象给定已知值。
- 赋值=对象被赋予超出定义点的已知值。
- 未初始化=尚未为对象给定已知值。
简单理解就是
int x = 0; // 初始化
int a; a = 1; //赋值
int c; // 未初始化未定义的行为
使用了未初始化变量的值是未定义行为的一种。
C++语言没有任何规则,来确定如果使用尚未给定已知值的变量的值会发生什么。因此,如果确实这样做,将导致未定义的行为。
会导致的问题
- 程序每次运行时都会产生不同的结果。
- 程序始终会产生相同的错误结果。
- 程序的行为不一致(有时产生正确的结果,有时没有)。
- 程序似乎正在工作,但稍后在程序中产生错误的结果。
- 程序立即或稍后崩溃。
- 程序可以在某些编辑器上工作,但不能在其他编辑器上工作。
- 更改了一些其他看似无关的代码,程序却无法正常运行。
由实现定义的行为和未指定行为
由实现定义的行为(Implementation-defined behavior)意味着某些语法的行为 由实现(编辑器)定义。这样的行为必须一致并记录在案,但不同的编辑器可能会产生不同的结果。
#include <iostream>
int main() {
std::cout << sizeof(int);// 4
return 0;
}大多数编辑器上,输出是 4,但可能在某些编辑器上输出 2。
未指定的行为(unspecified behavior)几乎与实现定义的行为相同,行为由实现决定,但实现不需要记录该行为。
命名规则和关键字
关键字
c++保留一组 92 个单词(从 c++23)供自己使用,这些词被称为关键字(保留字)。
并且每个关键字在 c++中都有特殊含义。
提示
熟记关键字将对你的代码水平有很大的提升,将为你提供强有力的帮助。
C++还有一些特殊标识符override,final,import,module。在某些情况中,它们具有特殊含义。
多看!多记!多练!
命名规则
变量(或函数、其他类型)的名称称为标识符。命名标识符要遵循一些规则。
- 标识符不能是关键字。
- 标识符只能由字母(大小写)、数字和下划线组成。不能包含特殊符号(下划线除外)和空格
- 标识符只能以字母开头或下划线开头,不能以数字开头。
- C++严格区分大小写。
实践
变量命名
int value;// √
int Value;// 不推荐
int VALUE;// 不推荐函数命名
蛇形命名法或驼峰命名法
int my_name_fn;//蛇形命名
int my_name_fn();// 蛇形命名
int myNameFn;//驼峰命名
int myNameFn();//驼峰命名空白字符与代码样式
空白字符用于格式化,空白字符通常指空格、制表符、换行符。
通常使用空白字符进行格式化代码,使其更加美观易读。
语言元素必须用空白字符分割
例如声明变量时
int a; // 关键字或标识符要使用空白字符区分开来函数的返回类型和名称必须分割
int main();对于空白符,编辑器不关心用了多少个
int a;
int a;
int a;//没有区别预处理器指令必须单独放在一行
如:
#include <iostream>
#include <string>字符串中空白字符也算有效字符
std::cout<<"hello world";
std::cout<<"hello world";
// 含义不同空格真实有效,空格会被原封不动输出
// 在字符串中不允许换行
std::cout<<"hello
world"; // 编译器报错代码样式
在 google C++风格上
int main(){
// 开头的大括号与语句同行
}但大多数下
int main()
{
//大括号开始和结束分别占一行更加直观,更加提高可读性
}自动格式化快捷键
打开 visio studio -> 编辑 -> 高级 -> 自动格式化选项
也可以自定义设置
工具 -> 选项 -> 文本编辑器 -> c/c++ -> 代码样式 -> 格式设置
字面量和操作符
字面量
提示
字面量也称为常量,是源码中的固定值。
什么样的值是字面量?
std::cout << "hello world";
int a{1};像上面那种hello world和1都是字面量,也就是常量。
注意区分,虽然将1赋值给了a,但是常量说的是1,并不是a;
常量和变量差异
#include <iostream>
int main(){
std::cout << 2 << '\n'; // 打印常量
int b {3};
std::cout << b << '\n'; // 打印变量
return 0;
}上面那段代码可以区分,代码执行std::cout << 2 << '\n';时,值2被编译为可执行文件,可以直接使用。
当执行代码std::cout << b << '\n';时,编译器会获取 x 的内存位置,读取 x 的值并打印到控制台。
因此可看出两种区别,对于字面量则可以直接打印,对于变量,则需要从内存中获取值,后打印。
这也是为什么变量可修改,字面量(常量)不能更改的原因。
就像5 = 2;,并不能把 5 变成 2,并且这是一个错误语句。
关键
字面值是直接插入到源代码中的值,直接出现在可执行代码中(除非被优化)。
对象和变量表示保存值的内存位置。这些值按需获取。
操作符
操作符也可以叫运算符,只不过在 C++中除了我们常见的运算符之外还有生活中不常见的。
2 + 3 = 5;
// 在数学中表示操作数2和操作数3通过操作符+得出值5除了+号操作符之外,C++中还有许多有用的操作符。
重要
包括加法+、减法-、乘法*、除法/。C++中还有赋值=、插入<<、提取>>、和相等==操作符。当然也包括一些关键字操作符new、delete和throw。
C++中的操作符有四种不同的操作方法:
- 一元操作符作用域一个操作数
- 例如
// 操作符 减法- 给操作数2 产生新的值 -2
int -2;- 二元操作符作用于两个操作数
- 例如
// 二元操作是最常用的一种操作
// 通常是左操作数和右操作数
1+2;
3-2;
1*1;
2/1;
// 还包括 插入<< 和 提取>>
std::cin >> a;
std::cout << 666;- 三元操作符作用于三个操作数
- 零元操作符作用于零操作数
操作符优先级
操作符的优先级遵循数学运算符优先级规则。
操作符返回值
C++中的大多数操作符使用它们的操作数来计算返回值。
#include <iostream>
int main() {
int y;
int x = y = 2;
std::cout << x << '\n' << y;
// 结果
// 2
// 2
return 0;
// std::cout << x << '\n' << y;
// 先将 - (std::cout << x)运算返回std::cout
// 再执行(std::cout << '\n') 之后返回std::cout
// 在执行(std::cout<< y)
}表达式简介
表达式
暂时可以理解为上学时所了解的数学表达式
计算表达式时,将计算表达式中的每一项,直到生成最终的单个值。
例如:
int getNum()
{
return 2;
}
int main()
{
int a{4}; //使用字面量常量4,初始化a
int b{2+2}; //使用计算结果4,初始化b
int c{(2*2)+2}; //使用计算结果6.初始化c
int d{b}; // 使用变量b的值初始化d
int e{getNum()}; // 使用函数返回值初始化e
return 0;
}语法分解
类型 标识符 {表达式};
单个值也可以称为一个表达式。
字面量常量的计算结果通常是它们自己。
例如:
int x = 1;
int a { 2 };涉及具有副作用的运算符表达式
int a = 2
int b = 1 + 2
std::cout << aDANGER
表达式不会以分号结尾,并且不能单独编译运行。
2 //编译器会报错
2; // 没有任何结果
int a = 1 + 2
3;// 编译器会报错
int a = { 2 + 3; }; // 编译器报错表达式语句
构成:
表达式语句由表达式跟其后的分号组成的语句
在表达式语句中使用表达式时,将丢弃由表达式生成的返回值(因为它为被使用)。
子表达式、完整表达式和复合表达式
//子表达式是用作操作数的表达式
int x = 1+2;
// 其中x和1+2、是子表达式。
// 1和2也是子表达式
// 完整表达式是操作符加上对应的操作数。2、2 + 3 和 x = 4 + 5 都是完整表达式。
// 复合表达式是包含两个或多个操作符的表达式
// x = 4 + 5 是一个复合表达式,因为它包含两个运算符(=和+)。2 和 2 + 3 不是复合表达式。开始第一个程序
int main
{
std::cout << "输入一个数字:";
int num{};
std::cin >> num;
std::cout << "数字 " << num << "的两倍是:" << num * 2 << "\n";
return 0;
}