Skip to content

认识 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 分配器、本地化库、异常处理类、杂项支持库。

开始

变量初始化和赋值

初始化有默认初始化、拷贝初始化、直接初始化等

c++
#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 - 结束符/换行符

c++
std::cout << "Hello";
std::cout << "World";
》 HelloWorld

std::cout << "Hello" << std::endl;
std::cout << "World" << std::endl;
》 Hello
》 World

'\n - 换行符'

c++
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可以输出到控制台信息,那么如何获取控制台输入的信息呢?

c++
#include <iostream>

int main() {
	int a{};
	std::cin >> a;
	std::cout << "a = " << a << std::endl;
	return 0;
}

执行命令会发现,控制台让我们输入,输入完成后就会输出我们输入的值

通过以上操作我们知道std::cin语句可以获取输入信息

未初始化的变量

在 C++中,系统不会自动给初始化变量赋值,因此,当变量被分配到内存地址来存储数据时,该变量 的默认值可能是内存地址中已经存在的任何(垃圾)值!

尚未给定值的变量成为未初始化变量

不过若出现未初始化变量时,程序会捕获到错误error C4700: 使用了未初始化的局部变量...

c++
#include <iostream>

int main() {
	int x;
	std::cout << x;
	return 0;
}
shell
error C4700: 使用了未初始化的局部变量“x”

如果要避免上述报错,一定要运行

使用技巧骗过编辑器

c++
#include <iostream>


void doNothing(int&) {
	// 暂时不需要理解&的用途,让编辑器理解变量已被使用
}
int main() {
	int x;
	doNothing(x);//让编辑器认为x会被写入数据
	std::cout << x;//结果是未知的
	return 0;
}

警告

使用未初始化变量是一个很严重的问题!

扼要重述:

  • 初始化=在定义点为对象给定已知值。
  • 赋值=对象被赋予超出定义点的已知值。
  • 未初始化=尚未为对象给定已知值。

简单理解就是

c++
int x = 0; // 初始化
int a; a = 1; //赋值
int c; // 未初始化

未定义的行为

使用了未初始化变量的值是未定义行为的一种。

C++语言没有任何规则,来确定如果使用尚未给定已知值的变量的值会发生什么。因此,如果确实这样做,将导致未定义的行为。

会导致的问题

  • 程序每次运行时都会产生不同的结果。
  • 程序始终会产生相同的错误结果。
  • 程序的行为不一致(有时产生正确的结果,有时没有)。
  • 程序似乎正在工作,但稍后在程序中产生错误的结果。
  • 程序立即或稍后崩溃。
  • 程序可以在某些编辑器上工作,但不能在其他编辑器上工作。
  • 更改了一些其他看似无关的代码,程序却无法正常运行。

由实现定义的行为和未指定行为

由实现定义的行为(Implementation-defined behavior)意味着某些语法的行为 由实现(编辑器)定义。这样的行为必须一致并记录在案,但不同的编辑器可能会产生不同的结果。

c++
#include <iostream>

int main() {
	std::cout << sizeof(int);// 4
	return 0;
}

大多数编辑器上,输出是 4,但可能在某些编辑器上输出 2。

未指定的行为(unspecified behavior)几乎与实现定义的行为相同,行为由实现决定,但实现不需要记录该行为。


命名规则和关键字

关键字

c++保留一组 92 个单词(从 c++23)供自己使用,这些词被称为关键字(保留字)。

并且每个关键字在 c++中都有特殊含义。

alignas
const_cast
int
static_assert
alignof
continue
long
static_cast
and
co_await (C++20)
mutable
struct
and_eq
co_return (C++20)
namespace
switch
asm
co_yield (C++20)
new
template
auto
decltype
noexcept
this
bitand
default
not
thread_local
bitor
delete
not_eq
throw
bool
do
nullptr
true
break
double
operator
try
case
dynamic_cast
or
typedef
catch
else
or_eq
typeid
char
enum
private
typename
char8_t (C++20)
explicit
protected
union
char16_t
export
public
unsigned
char32_t
extern
register
using
class
false
reinterpret_cast
virtual
compl
float
requires (C++20)
void
concept (C++20)
for
return
volatile
const
friend
short
wchar_t
consteval (C++20)
goto
signed
while
constexpr
if
sizeof
xor
constinit (C++20)
inline
static
xor_eq

提示

熟记关键字将对你的代码水平有很大的提升,将为你提供强有力的帮助。

C++还有一些特殊标识符override,final,import,module。在某些情况中,它们具有特殊含义。

多看!多记!多练!

命名规则

变量(或函数、其他类型)的名称称为标识符。命名标识符要遵循一些规则。

  • 标识符不能是关键字。
  • 标识符只能由字母(大小写)、数字和下划线组成。不能包含特殊符号(下划线除外)和空格
  • 标识符只能以字母开头或下划线开头,不能以数字开头。
  • C++严格区分大小写。

实践

变量命名

c++
int value;// √
int Value;// 不推荐
int VALUE;// 不推荐

函数命名

蛇形命名法或驼峰命名法

C++
int my_name_fn;//蛇形命名
int my_name_fn();// 蛇形命名

int myNameFn;//驼峰命名
int myNameFn();//驼峰命名

空白字符与代码样式

空白字符用于格式化,空白字符通常指空格、制表符、换行符。

通常使用空白字符进行格式化代码,使其更加美观易读。

语言元素必须用空白字符分割

例如声明变量时

C++
int a; // 关键字或标识符要使用空白字符区分开来

函数的返回类型和名称必须分割

C++
int main();

对于空白符,编辑器不关心用了多少个

C++
int a;
int    a;
int        a;//没有区别

预处理器指令必须单独放在一行

如:

C++
#include <iostream>
#include <string>

字符串中空白字符也算有效字符

C++
std::cout<<"hello world";
std::cout<<"hello    world";
// 含义不同空格真实有效,空格会被原封不动输出

// 在字符串中不允许换行
std::cout<<"hello
world"; // 编译器报错

代码样式

在 google C++风格上

C++
int main(){
  // 开头的大括号与语句同行
}

但大多数下

C++
int main()
{
  //大括号开始和结束分别占一行更加直观,更加提高可读性
}

自动格式化快捷键

打开 visio studio -> 编辑 -> 高级 -> 自动格式化选项

也可以自定义设置

工具 -> 选项 -> 文本编辑器 -> c/c++ -> 代码样式 -> 格式设置

字面量和操作符

字面量

提示

字面量也称为常量,是源码中的固定值。

什么样的值是字面量?

C++
std::cout << "hello world";
int a{1};

像上面那种hello world1都是字面量,也就是常量。

注意区分,虽然将1赋值给了a,但是常量说的是1,并不是a;

常量和变量差异

C++
#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++中除了我们常见的运算符之外还有生活中不常见的。

C++
2 + 3 = 5;
// 在数学中表示操作数2和操作数3通过操作符+得出值5

除了+号操作符之外,C++中还有许多有用的操作符。

重要

包括加法+、减法-、乘法*、除法/。C++中还有赋值=、插入<<、提取>>、和相等==操作符。当然也包括一些关键字操作符newdeletethrow

C++中的操作符有四种不同的操作方法:

  • 一元操作符作用域一个操作数
    • 例如
C++
// 操作符 减法- 给操作数2 产生新的值 -2
int -2;
  • 二元操作符作用于两个操作数
    • 例如
C++
// 二元操作是最常用的一种操作
// 通常是左操作数和右操作数
1+2;
3-2;
1*1;
2/1;
// 还包括 插入<< 和 提取>>
std::cin >> a;
std::cout << 666;
  • 三元操作符作用于三个操作数
  • 零元操作符作用于零操作数

操作符优先级

操作符的优先级遵循数学运算符优先级规则。

操作符返回值

C++中的大多数操作符使用它们的操作数来计算返回值。

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)
}

表达式简介

表达式

暂时可以理解为上学时所了解的数学表达式

计算表达式时,将计算表达式中的每一项,直到生成最终的单个值。

例如:

C++
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;
}

语法分解

类型 标识符 {表达式};

单个值也可以称为一个表达式。

字面量常量的计算结果通常是它们自己。

例如:

C++
int x = 1;
int a { 2 };

涉及具有副作用的运算符表达式

C++
int a = 2
int b = 1 + 2
std::cout << a

DANGER

表达式不会以分号结尾,并且不能单独编译运行。

C++
2 //编译器会报错
2; // 没有任何结果

int a = 1 + 2
	3;// 编译器会报错

int a = { 2 + 3; }; // 编译器报错

表达式语句

构成:

表达式语句由表达式跟其后的分号组成的语句

在表达式语句中使用表达式时,将丢弃由表达式生成的返回值(因为它为被使用)。

子表达式、完整表达式和复合表达式

C++
//子表达式是用作操作数的表达式
int x = 1+2;
// 其中x和1+2、是子表达式。
// 1和2也是子表达式

// 完整表达式是操作符加上对应的操作数。2、2 + 3 和 x = 4 + 5 都是完整表达式。

// 复合表达式是包含两个或多个操作符的表达式
// x = 4 + 5 是一个复合表达式,因为它包含两个运算符(=和+)。2 和 2 + 3 不是复合表达式。

开始第一个程序

C++
int main
{
  std::cout << "输入一个数字:";
  int num{};
  std::cin >> num;
  std::cout << "数字 " << num << "的两倍是:" << num * 2 << "\n";
  return 0;
}