c++基础语法
文章目录
- 1.第一个c++程序
- 2.c++的关键字
- 3.c++数据类型
- 4.c++运算符
- 5.c++分支结构
- 5.1. `if` 语句
- 5.2. `switch` 语句
- 6.c++循环
- 6.1. `for` 循环
- 6.2. `while` 循环
- 6.3. `do-while` 循环
- 6.4. `break` 和 `continue` 语句
- 7.c++函数
- 7.1函数定义的基本结构
- 7.2一个简单的函数
- 7.3带参数的函数
- 7.4返回值的函数
- 7.5默认参数
- 7.6函数重载
- 7.7内联函数和 constexpr
- 8.数组
- 8.一维数组
- 8.2多维数组
- 8.3C++标准库中的数组
- 8.4动态数组
- 8.5传递数组到函数
- 9.字符串
- 9.1. C风格字符串
- 9.2. `std::string`类
- 9.3. `std::string_view`(C++17)
- 9.4. 字符串字面量
- 9.5. 字符串和数组的转换
- 10.指针
- 10.1指针的基本概念
- 指针运算
- 10.2指针和数组
- 10.3指针和函数
- 10.4指针和动态内存分配
- 10.5指针和const
- 10.6指针的指针和多重指针
- 10.7智能指针(C++11)
- 11.结构体
- 11.1声明结构体
- 11.2创建结构体变量
- 11.3初始化结构体
- 11.4访问结构体成员
- 11.5结构体作为函数参数
- 11.6结构体和指针
- 11.7结构体数组
- 11.8结构体和动态内存分配
- 11.9结构体和类
- 11.10结构体与继承
- 11.11结构体字面量(C++20)
C++ 是由 Bjarne Stroustrup 于 1979 年在新泽西州美利山贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,最初命名为带类的C,后来在 1983 年更名为 C++。
1.第一个c++程序
#include <iostream>
using namespace std;
// main() 是程序开始执行的地方
int main() {
cout << "Hello World"; // 输出 Hello World
return 0;
}
接下来我们讲解一下上面这段程序:
#include <iostream>
:这是一个预处理指令,告诉编译器包含标准输入输出流库iostream。这个库包含了进行输入输出操作所需的函数和对象,比如cout
用于输出。using namespace std;
:这行代码告诉编译器在程序中使用std
命名空间中的所有名称,而不需要每次都写std::
前缀。std
是C++标准库的命名空间,cout
、cin
等都位于这个命名空间中。int main() {
:这是主函数的开始,main
函数是每个C++程序的入口点,程序执行从这里开始。int
表示main
函数返回一个整数值,按照惯例,返回0表示程序成功执行结束。cout << "Hello World";
:这行代码使用cout
对象(来自iostream库)来输出字符串"Hello World"到控制台。<<
是插入操作符,用于将数据发送到输出流。return 0;
:这行代码表示main
函数返回0,通常表示程序执行成功且没有错误。
2.c++的关键字
关键字 | 关键字 | 关键字 | 关键字 |
---|---|---|---|
alignas | alignof | and | and_eq |
asm | auto | bool | break |
case | catch | char | char16_t |
char32_t | class | compl | const |
const_cast | constexpr | continue | decltype |
default | delete | do | dynamic_cast |
else | enum | 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 | throw |
true | try | typedef | typeid |
typename | union | unsigned | using |
virtual | void | volatile | wchar_t |
while |
3.c++数据类型
-
整型:
int integer = 10; // 整型变量 short shortInt = 10; // 短整型变量 long longInt = 10000000000L; // 长整型变量,L表示长整型字面量 long long longLongInt = 10000000000000000LL; // 长长整型变量,LL表示长长整型字面量 unsigned int unsignedInt = 10; // 无符号整型变量
-
浮点型:
float floatValue = 10.5f; // 单精度浮点型变量,f表示float字面量 double doubleValue = 10.5; // 双精度浮点型变量,默认为double类型 long double longDoubleValue = 10.5L; // 扩展精度浮点型变量,L表示long double字面量
-
字符型:
char charValue = 'A'; // 字符型变量 wchar_t wideCharValue = L'A'; // 宽字符型变量,L表示宽字符字面量
-
布尔型:
bool boolValue = true; // 布尔型变量
-
数组:
int intArray[5] = {1, 2, 3, 4, 5}; // 整型数组
-
结构体:
struct Person { char name[50]; int age; }; Person person = {"John", 30}; // 结构体变量
-
联合体:
union Data { int i; float f; char str[20]; }; Data data; // 联合体变量
-
枚举:
enum Color {RED, GREEN, BLUE}; // 枚举类型 Color color = GREEN; // 枚举变量
-
指针类型:
int *intPtr = &integer; // 指向整型的指针
-
引用类型:
int integer = 10; int &refInteger = integer; // 整型的引用
-
空类型:
void function() {} // 返回void类型的函数
-
自动类型推导:
auto autoInt = 10; // 自动推导为整型 auto autoDouble = 10.5; // 自动推导为双精度浮点型
-
类类型:
class MyClass { public: void myMethod() {} }; MyClass myObject; // 类型为MyClass的对象
-
模板类型:
template <typename T> void myFunction(T param) {} myFunction(10); // 使用整型实例化模板 myFunction(10.5); // 使用浮点型实例化模板
-
C++11及以后版本新增类型:
nullptr_t nullptrValue = nullptr; // nullptr类型 char16_t char16Value = u'A'; // UTF-16字符 char32_t char32Value = U'A'; // UTF-32字符
4.c++运算符
-
算术运算符:
+
加法-
减法*
乘法/
除法%
取模(求余)++
增加(前置或后置)--
减少(前置或后置)
int a = 5, b = 3; int sum = a + b; // 加法 int difference = a - b; // 减法 int product = a * b; // 乘法 int quotient = a / b; // 除法 int remainder = a % b; // 取模 a++; // 前置增加 ++a; // 后置增加 --a; // 前置减少 a--; // 后置减少
-
关系运算符:
==
等于!=
不等于>
大于<
小于>=
大于等于<=
小于等于
if (a == b) { // 等于 } if (a != b) { // 不等于 } if (a > b) { // 大于 } if (a < b) { // 小于 } if (a >= b) { // 大于等于 } if (a <= b) { // 小于等于 }
-
逻辑运算符:
&&
逻辑与||
逻辑或!
逻辑非
bool isTrue = (a == b) && (a > b); // 逻辑与 bool isFalse = (a == b) || (a < b); // 逻辑或 bool notTrue = !(a == b); // 逻辑非
-
位运算符:
&
位与|
位或^
位异或~
位取反<<
左移>>
右移
int c = 5, d = 3; int bitwiseAnd = c & d; // 位与 int bitwiseOr = c | d; // 位或 int bitwiseXor = c ^ d; // 位异或 int bitwiseNot = ~c; // 位取反 int leftShift = c << 1; // 左移 int rightShift = c >> 1; // 右移
-
赋值运算符:
=
赋值+=
加后赋值-=
减后赋值*=
乘后赋值/=
除后赋值%=
取模后赋值<<=
左移后赋值>>=
右移后赋值&=
位与后赋值|=
位或后赋值^=
位异或后赋值
a = b; // 赋值 a += b; // 加后赋值 a -= b; // 减后赋值 a *= b; // 乘后赋值 a /= b; // 除后赋值 a %= b; // 取模后赋值 a <<= b; // 左移后赋值 a >>= b; // 右移后赋值 a &= b; // 位与后赋值 a |= b; // 位或后赋值 a ^= b; // 位异或后赋值
-
成员访问运算符:
.
成员访问->
指针成员访问
struct Person { char name[50]; }; Person person = {"John"}; cout << person.name; // 成员访问 Person* personPtr = &person; cout << personPtr->name; // 指针成员访问
-
其他运算符:
sizeof
计算大小?:
条件运算符(三元运算符)&
取地址*
解引用new
分配内存delete
释放内存
int size = sizeof(int); // 计算大小 int max = (a > b) ? a : b; // 条件运算符 int* ptr = &a; // 取地址 int value = *ptr; // 解引用 int* dynArray = new int[10]; // 分配内存 delete[] dynArray; // 释放内存
5.c++分支结构
C++中的选择程序设计主要依赖于条件语句,这些语句允许程序根据不同的条件执行不同的代码块。C++中有两种主要的选择语句:if
语句和 switch
语句。
5.1. if
语句
if
语句用于在满足特定条件时执行一段代码。它还可以与 else
和 else if
结合使用,以处理多个条件。
基本的 if
语句:
if (condition) {
// 如果条件为真,则执行的代码
}
带有 else
的 if
语句:
if (condition) {
// 如果条件为真,则执行的代码
} else {
// 如果条件为假,则执行的代码
}
带有 else if
的 if
语句:
if (condition1) {
// 如果条件1为真,则执行的代码
} else if (condition2) {
// 如果条件1为假且条件2为真,则执行的代码
} else {
// 如果所有条件都不满足,则执行的代码
}
5.2. switch
语句
switch
语句用于根据变量的值执行不同的代码块。它比多个 if-else
语句更清晰,特别是当需要检查同一个变量的多个值时。
switch (variable) {
case value1:
// 如果 variable 等于 value1,则执行的代码
break;
case value2:
// 如果 variable 等于 value2,则执行的代码
break;
// ... 更多的 case
default:
// 如果 v
6.c++循环
在C++中,循环是一种控制结构,它允许代码多次执行。C++提供了三种主要的循环语句:for
循环、while
循环和 do-while
循环。
6.1. for
循环
for
循环是一种预先测试循环,通常用于当你需要知道循环次数时。
for (initialization; condition; increment) {
// 循环体
}
- initialization:初始化部分,通常用于声明循环计数器。
- condition:条件测试,如果为真,循环继续执行。
- increment:更新部分,通常用于更新循环计数器。
示例:打印从1到10的数字。
for (int i = 1; i <= 10; i++) {
std::cout << i << " ";
}
6.2. while
循环
while
循环是一种后测试循环,只要条件为真,循环就会继续执行。
while (condition) {
// 循环体
}
- condition:条件测试,如果为真,循环继续执行。
示例:打印从1到10的数字。
int i = 1;
while (i <= 10) {
std::cout << i << " ";
i++;
}
6.3. do-while
循环
do-while
循环也是一种后测试循环,与 while
循环不同的是,do-while
循环至少会执行一次,因为条件测试是在循环体执行之后进行的。
do {
// 循环体
} while (condition);
- condition:条件测试,如果为真,循环继续执行。
示例:至少打印一次,然后检查条件。
int i = 1;
do {
std::cout << i << " ";
i++;
} while (i <= 10);
6.4. break
和 continue
语句
break
:立即退出循环。continue
:跳过当前迭代的剩余部分,并继续下一次迭代。
示例:使用 break
和 continue
。
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // 当 i 等于 5 时,退出循环
}
std::cout << i << " ";
}
std::cout << std::endl;
for (int i = 0; i < 10; i++) {
if (i % 2 != 0) {
continue; // 跳过奇数
}
std::cout << i << " "; // 只打印偶数
}
7.c++函数
在C++中,函数是执行特定任务的自包含代码块。函数可以接收输入(参数),执行一些操作,并返回结果。以下是C++函数的一些基本组成部分和特性:
7.1函数定义的基本结构
返回类型 函数名(参数列表) {
// 函数体
// 可以包含局部变量声明、语句、控制流语句等
return 返回值; // 根据返回类型返回值
}
- 返回类型:函数执行完毕后返回的数据类型。
- 函数名:函数的唯一标识符。
- 参数列表:函数接收的参数,参数之间用逗号分隔。如果函数不接受参数,参数列表为空。
- 函数体:大括号
{}
内包含的代码,定义了函数的具体行为。
7.2一个简单的函数
#include <iostream>
// 无参数,无返回值的函数
void printHello() {
std::cout << "Hello, World!" << std::endl;
}
int main() {
printHello(); // 调用函数
return 0;
}
7.3带参数的函数
#include <iostream>
// 带参数的函数,无返回值
void printNumber(int num) {
std::cout << "The number is: " << num << std::endl;
}
int main() {
printNumber(42); // 调用函数,并传递参数
return 0;
}
7.4返回值的函数
#include <iostream>
// 带参数,有返回值的函数
int addNumbers(int a, int b) {
return a + b; // 返回两个数的和
}
int main() {
int sum = addNumbers(5, 10); // 调用函数,并接收返回值
std::cout << "The sum is: " << sum << std::endl;
return 0;
}
7.5默认参数
C++允许为函数参数提供默认值,这样在调用函数时可以省略这些参数。
#include <iostream>
// 带有默认参数的函数
void printInfo(int age, std::string name = "Unknown") {
std::cout << "Age: " << age << ", Name: " << name << std::endl;
}
int main() {
printInfo(25); // 使用默认的name参数
printInfo(30, "Alice"); // 提供name参数
return 0;
}
7.6函数重载
C++支持函数重载,即同一个函数名可以用于不同的函数,只要它们的参数列表不同(参数类型、数量或顺序不同)。
#include <iostream>
// 函数重载示例
void printMessage() {
std::cout << "No argument message" << std::endl;
}
void printMessage(const std::string& message) {
std::cout << "Message: " << message << std::endl;
}
int main() {
printMessage(); // 调用无参数版本
printMessage("Hello, World!"); // 调用有参数版本
return 0;
}
7.7内联函数和 constexpr
- 内联函数:使用
inline
关键字声明的函数,建议编译器在编译时将其内联展开,减少函数调用的开销。 - constexpr函数:用于声明常量表达式函数,其返回值必须在编译时可知。
#include <iostream>
inline int max(int a, int b) {
return a > b ? a : b;
}
constexpr int add(int a, int b) {
return a + b;
}
int main() {
std::cout << "Max of 5 and 10 is: " << max(5, 10) << std::endl;
const int sum = add(3, 4);
return 0;
}
函数是C++中实现代码复用和模块化的基本单位,合理使用函数可以提高代码的可读性和可维护性。
8.数组
在C++中,数组是一种基本的数据结构,用于存储相同类型的多个元素。数组可以是一维的或多维的。以下是C++中数组的一些关键特性和用法。
8.一维数组
一维数组是相同数据类型的元素的集合。
声明和初始化:
// 声明一个整型数组,包含5个元素
int arr[5];
// 声明并初始化一个整型数组
int arr[] = {1, 2, 3, 4, 5};
访问数组元素:
数组元素通过索引访问,索引从0开始。
std::cout << arr[0]; // 输出第一个元素
数组的大小:
在C++中,可以使用sizeof
运算符获取数组的大小,单位是字节,或者使用数组的内置属性size
(C++11及以后版本)。
std::cout << sizeof(arr) / sizeof(arr[0]); // 输出数组元素个数
std::cout << arr.size(); // C++11及以后版本
8.2多维数组
多维数组可以看作是数组的数组。
声明和初始化:
// 声明一个二维数组,3行2列
int arr[3][2];
// 声明并初始化一个二维数组
int arr[3][2] = {{1, 2}, {3, 4}, {5, 6}};
访问多维数组元素:
std::cout << arr[0][1]; // 输出第一行第二列的元素
8.3C++标准库中的数组
C++标准库提供了std::array
和std::vector
,它们提供了更多的功能和灵活性。
std::array:
#include <array>
#include <iostream>
std::array<int, 5> arr = {1, 2, 3, 4, 5};
std::cout << arr[2]; // 输出第三个元素
std::vector:
#include <vector>
#include <iostream>
std::vector<int> vec = {1, 2, 3, 4, 5};
std::cout << vec[2]; // 输出第三个元素
vec.push_back(6); // 添加一个新元素
8.4动态数组
在C++中,可以使用new
和delete
操作符来创建和销毁动态数组。
int* arr = new int[5]; // 创建动态数组
arr[0] = 10; // 初始化元素
delete[] arr; // 销毁动态数组
8.5传递数组到函数
在C++中,数组作为参数传递给函数时,实际上是通过指针传递的。
#include <iostream>
void printArray(int arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
printArray(arr, 5); // 传递数组和大小
return 0;
}
数组是C++中处理同类数据集合的重要工具,但使用时需要注意边界检查,以避免越界访问等常见错误。随着C++标准的发展,std::array
和std::vector
等容器类提供了更安全和方便的选择。
9.字符串
在C++中,字符串处理是一个非常重要的部分。C++提供了多种方式来处理字符串,主要包括C风格字符串、std::string
类和C++17中引入的std::string_view
。下面详细介绍这些字符串处理方式。
9.1. C风格字符串
C风格字符串是字符数组,以空字符'\0'
结尾。它们是最基本的字符串表示形式,但在使用时需要格外小心,因为它们不提供边界检查,容易造成缓冲区溢出等安全问题。
声明和初始化:
char str[] = "Hello, World!"; // 自动添加'\0'结尾
char str2[20] = "Hello"; // 需要手动确保有足够的空间
操作C风格字符串的函数:
strlen()
:计算字符串长度(不包括空字符)。strcpy()
:复制字符串。strcat()
:连接字符串。strcmp()
:比较字符串。strchr()
:查找字符在字符串中的位置。strrchr()
:从字符串末尾开始查找字符。
9.2. std::string
类
std::string
是C++标准库中的一个类,提供了丰富的方法来操作字符串。它是处理字符串的首选方式,因为它提供了类型安全、内存管理和其他便利的操作。
声明和初始化:
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!"; // 直接使用字符串字面量初始化
std::string anotherStr = "Another string";
// 获取字符串长度
std::cout << str.length() << std::endl;
// 连接字符串
std::string concatenated = str + anotherStr;
std::cout << concatenated << std::endl;
// 比较字符串
if (str > anotherStr) {
std::cout << str << " is greater than " << anotherStr << std::endl;
}
// 查找子串
std::size_t found = str.find("World");
if (found != std::string::npos) {
std::cout << "Found 'World' at position " << found << std::endl;
}
// 替换字符
str.replace(7, 5, anotherStr);
std::cout << str << std::endl;
// 访问字符
char firstChar = str[0];
std::cout << "First character: " << firstChar << std::endl;
return 0;
}
9.3. std::string_view
(C++17)
std::string_view
是一个非拥有的字符串视图,用于高效地处理字符串,而不需要复制。它特别适用于函数参数,以避免复制大型字符串。
声明和使用:
#include <iostream>
#include <string_view>
int main() {
std::string str = "Hello, World!";
std::string_view view(str);
// 获取字符串长度
std::cout << view.length() << std::endl;
// 访问字符
std::cout << "First character: " << view[0] << std::endl;
// 比较字符串
if (view == str) {
std::cout << "The string_view is equal to the std::string" << std::endl;
}
return 0;
}
9.4. 字符串字面量
在C++中,字符串字面量是const char
数组,因此它们是不可修改的。
const char* literal = "String literal";
9.5. 字符串和数组的转换
有时候,你可能需要在std::string
和C风格字符串之间进行转换。
std::string str = "Hello";
const char* cstr = str.c_str(); // 将std::string转换为C风格字符串
char buffer[13];
std::strcpy(buffer, cstr); // 将C风格字符串复制到字符数组
std::string
是处理字符串的首选方式,因为它提供了类型安全、内存管理和其他便利的操作。C风格字符串仍然在使用,尤其是在与C代码交互或处理旧代码库时。std::string_view
提供了一种高效处理字符串的方式,尤其是在性能敏感的场景中。
10.指针
在C++中,指针是一种特殊的变量,它存储了另一个变量的内存地址。指针是C++中非常强大的特性之一,但同时也需要小心使用,因为不当的指针操作可能导致程序崩溃或安全漏洞。
10.1指针的基本概念
指针变量可以指向任何类型的数据,包括基本数据类型、复合数据类型、函数和对象。指针的声明需要指定它所指向的变量类型。
声明指针:
int *ptr; // 声明一个指向整型数据的指针
初始化指针:
int var = 10;
int *ptr = &var; // ptr现在指向var的地址
解引用指针:
int value = *ptr; // 通过指针ptr获取var的值
指针运算
- 地址运算符
&
:取变量的地址。 - 解引用运算符
*
:获取指针指向的值。
10.2指针和数组
指针和数组在C++中密切相关。数组名本身可以作为指向数组首元素的指针。
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // ptr指向数组的第一个元素
10.3指针和函数
函数的参数和返回值也可以是指针。
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
swap(&x, &y);
return 0;
}
10.4指针和动态内存分配
C++提供了new
和delete
操作符来动态分配和释放内存。
int *ptr = new int; // 分配一个整型内存空间,并初始化为0
*ptr = 10; // 设置ptr指向的值为10
delete ptr; // 释放内存
对于数组:
int *arr = new int[5]; // 分配一个整型数组
delete[] arr; // 释放数组内存
10.5指针和const
const int *ptr;
:ptr可以指向任何const int,但ptr本身可以改变。int *const ptr;
:ptr指向的地址可以改变,但ptr指向的值不能改变。const int *const ptr;
:ptr既不能改变指向的地址,也不能改变指向的值。
10.6指针的指针和多重指针
多重指针是指向另一个指针的指针。
int var = 10;
int *ptr = &var;
int **ptrToPtr = &ptr; // ptrToPtr指向ptr
10.7智能指针(C++11)
C++11引入了智能指针,它们可以自动管理内存,减少内存泄漏的风险。
std::unique_ptr
:独占所有权的智能指针。std::shared_ptr
:共享所有权的智能指针。std::weak_ptr
:用于打破std::shared_ptr
的循环引用。
#include <memory>
std::unique_ptr<int> uniquePtr(new int(10)); // 自动释放内存
std::shared_ptr<int> sharedPtr(new int(20)); // 引用计数自动管理内存
指针是C++中非常强大的工具,但也需要谨慎使用。正确使用指针可以提高程序的性能和灵活性,而错误的指针操作则可能导致程序错误和安全问题。
11.结构体
在C++中,结构体(struct
)是一种复合数据类型,允许你将多个不同或相同类型的变量组合成一个单一的数据结构。结构体经常用于创建复杂的数据类型,以表示更高级的数据结构或对象。
11.1声明结构体
你可以这样声明一个结构体类型:
struct Person {
std::string name;
int age;
float height;
};
11.2创建结构体变量
声明结构体类型后,可以创建该类型的变量:
Person person1;
11.3初始化结构体
你可以在创建结构体变量时初始化它的成员:
Person person2{"Alice", 30, 5.5};
11.4访问结构体成员
你可以通过点(.
)操作符访问结构体的成员:
person1.name = "Bob";
person1.age = 25;
person1.height = 6.0;
11.5结构体作为函数参数
你可以将结构体作为参数传递给函数:
void printPerson(const Person& person) {
std::cout << "Name: " << person.name << ", Age: " << person.age << ", Height: " << person.height << std::endl;
}
int main() {
Person person = {"John", 28, 5.8};
printPerson(person);
return 0;
}
11.6结构体和指针
你可以使用指针来访问结构体成员:
Person* personPtr = &person1;
(*personPtr).name = "Charlie"; // 或者 personPtr->name = "Charlie";
11.7结构体数组
你可以创建结构体数组:
Person people[3] = {
{"John", 28, 5.8},
{"Alice", 30, 5.5},
{"Bob", 25, 6.0}
};
11.8结构体和动态内存分配
你可以使用new
操作符动态分配结构体:
Person* dynamicPerson = new Person{"Eve", 22, 5.7};
记得使用delete
释放动态分配的内存:
delete dynamicPerson;
11.9结构体和类
在C++中,struct
和class
几乎可以互换使用,区别在于默认的访问权限:struct
默认成员是public
,而class
默认成员是private
。
11.10结构体与继承
结构体也可以使用继承,但通常用于表示简单的数据聚合,而类用于表示更复杂的对象和行为。
11.11结构体字面量(C++20)
C++20引入了结构体字面量,允许你这样初始化结构体:
struct Person {
std::string name;
int age;
};
Person person = {"Dave", 35};
结构体是C++中非常有用的工具,它们允许你以结构化的方式组织数据。通过合理使用结构体,你可以创建清晰、可维护的代码。
这是C++的基本内容,请继续学习stl和面向对象的内容。