C++引用
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。
一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
引用必须在定义时初始化,并且一旦绑定到一个变量后,就不能再绑定到其他变量。
引用语法:
int a = 10;
int &ref = a;//ref是对a的引用
int &ref
表示ref
是一个int
类型的引用。ref
是a
的别名,对ref
的操作会直接作用于a
。
引用和指针
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用,引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
- 引用的对象必须是一个变量,而指针必须是一个地址。
创建引用
变量名称是变量附属在内存位置中的标签,可以将引用当成是变量附属在内存位置中的第二个标签
int i = 10;
可以为i声明引用变量, 符号&表示引用
int &r = i; double &s = d;
#include<iostearm>
using namespace std;
int main(){
int i;
double d;
int &r = i; //r是一个初始化为i的整型应用
double &s = d; //s是一个初始化为d的双浮点型应用
i = 5;
cout << "value of i :" << i << endl;
cout << "value of i reference :" << r << endl;
d = 12.2;
cout << "value of d :" << d << endl;
cout << "value of d reference :" << s << endl;
return 0 ;
}
将引用作为参数
#include<iostearm>
using namespace std;
void swap(int&x, int&y);
int main(){
int a = 100;
int b = 200;
cout << "指示前,a的值:" << a << endl;
cout << "指示前,b的值:" << b << endl;
swap(a,b);
cout << "交换后,a的值:" << a << endl;
cout << "交换后,b的值:" << b << endl;
return 0;
}
void swap(int&x, int&y);
{
int temp;
temp = x; //保存x的地址
x = y; //把y值赋值给x
y = temp; //把x值赋值给y
return
}
将引用作为返回值
返回引用,相当于返回一个隐形指针
#include<iostearm>
using namespace std;
double vals[] = {12.1, 32.3, 23.1, 98.3, 56.3};
double& setvalues(int i) //可直接引用i值
{
double& ref = vals[i];
return ref;
}
int main(){
cout << "改变前的数值" << endl;
for(int i = 0; i < 5; i++)
{
cout << "vals[" << i << "] ="
cout << vals[i] << endl;
}
setvalues(1) = 20.23;
setvalues(2) = 23.32;
cout << "改变后的值" << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "vals[" << i << "] = ";
cout << vals[i] << endl;
}
return 0;
}
当返回一个引用时,要注意被引用的对象不能超出作用域。所以返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。
int& func() {
int q;
//! return q; // 在编译时发生错误
static int x;
return x; // 安全,x 在函数作用域外依然是有效的
}
C++日期和时间
有四个与时间相关的类型:clock_t、time_t、size_t 和 tm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。结构类型 tm 把日期和时间以 C 结构的形式保存
关于日期和时间的重要函数:
time_t time : 该函数返回系统的当前日历时间,若系统没有时间,则返回-1;
char*ctime :返回一个表示当地时间的字符串指针;
#include<iostearm>
using namespace std;
int main(){
time_t now = time(0);//基于当前系统的当前日期时间
char* dt = ctime(&now)//将now转为字符串形式
cout << "本地日期和时间:" << dt << endl;
//把now转为tm结构
tm *gmtm = gmtime(&now);
dt = asctime(gmtm);
cout << "UTC日期和时间:" << dt <<endl;
}
使用tm结构格式化时间
tm 结构在 C/C++ 中处理日期和时间相关的操作时,显得尤为重要。tm 结构以 C 结构的形式保存日期和时间。大多数与时间相关的函数都使用了 tm 结构。
#include<iostearm>
#include<ctime>
using namespace std;
int main(){
time_t now = time(0);
cout << "1970到目前时间: " << now << endl;
tm *ltm = localtime(&now);
//使用箭头 -> 运算符来访问结构成员。输出tm结构的各个组成部分
cout << "年: " << 1900 + ltm -> tm_year << endl;
cout << "月: " << 1 + ltm -> tm_mon <<endl;
cout << "日: " <<ltm -> tm_day <<endl;
cout << "时间:" << ltm -> tm_hour <<":";
cout << ltm -> tm_min <<":";
cout << ltm -> tm_sec << endl;
}
C++基本的输入输出
标准输出流:cout;
标准输入流:cin;
标准错误流:cerr;和cout功能一致,只是没缓存立即输出;
标准日志流:clog; 和cout功能一致,有缓存;
使用 cerr 流来显示错误消息,而其他的日志消息则使用 clog 流来输出。
C++结构体
结构不同于数组,允许用户存储不同类型的数据项
定义结构
为了定义结构,必须使用struct语句,struct 语句定义了一个包含多个成员的新的数据类型。
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
访问结构成员
使用成员访问运算符(.)
#include <iostream>
#include <cstring>
using namespace std;
// 声明一个结构体类型 Books
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
Books Book1; // 定义结构体类型 Books 的变量 Book1
Books Book2; // 定义结构体类型 Books 的变量 Book2
// Book1 详述
strcpy( Book1.title, "C++ 教程");
strcpy( Book1.author, "Runoob");
strcpy( Book1.subject, "编程语言");
Book1.book_id = 12345;
// Book2 详述
strcpy( Book2.title, "CSS 教程");
strcpy( Book2.author, "Runoob");
strcpy( Book2.subject, "前端技术");
Book2.book_id = 12346;
// 输出 Book1 信息
cout << "第一本书标题 : " << Book1.title <<endl;
cout << "第一本书作者 : " << Book1.author <<endl;
cout << "第一本书类目 : " << Book1.subject <<endl;
cout << "第一本书 ID : " << Book1.book_id <<endl;
// 输出 Book2 信息
cout << "第二本书标题 : " << Book2.title <<endl;
cout << "第二本书作者 : " << Book2.author <<endl;
cout << "第二本书类目 : " << Book2.subject <<endl;
cout << "第二本书 ID : " << Book2.book_id <<endl;
return 0;
}
结构作为函数参数
#include <iostream>
#include <cstring>
using namespace std;
void printBook( struct Books book );
// 声明一个结构体类型 Books
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
Books Book1; // 定义结构体类型 Books 的变量 Book1
Books Book2; // 定义结构体类型 Books 的变量 Book2
// Book1 详述
strcpy( Book1.title, "C++ 教程");
strcpy( Book1.author, "Runoob");
strcpy( Book1.subject, "编程语言");
Book1.book_id = 12345;
// Book2 详述
strcpy( Book2.title, "CSS 教程");
strcpy( Book2.author, "Runoob");
strcpy( Book2.subject, "前端技术");
Book2.book_id = 12346;
// 输出 Book1 信息
printBook( Book1 );
// 输出 Book2 信息
printBook( Book2 );
return 0;
}
void printBook( struct Books book )
{
cout << "书标题 : " << book.title <<endl;
cout << "书作者 : " << book.author <<endl;
cout << "书类目 : " << book.subject <<endl;
cout << "书 ID : " << book.book_id <<endl;
}
指向结构的指针
#include <iostream>
#include <string>
using namespace std;
// 声明一个结构体类型 Books
struct Books
{
string title;
string author;
string subject;
int book_id;
// 结构体的构造函数(用于初始化对象)
Books(string t, string a, string s, int id)
: title(t), author(a), subject(s), book_id(id) {}
};
// 打印书籍信息的函数,接受一个指向 Books 结构体的指针
void printBookInfo(const Books* book) {
cout << "书籍标题: " << book->title << endl;
cout << "书籍作者: " << book->author << endl;
cout << "书籍类目: " << book->subject << endl;
cout << "书籍 ID: " << book->book_id << endl;
}
int main()
{
// 创建两本书的对象
Books Book1("C++ 教程", "Runoob", "编程语言", 12345);
Books Book2("CSS 教程", "Runoob", "前端技术", 12346);
// 使用指针指向这两本书的对象
Books* ptrBook1 = &Book1;
Books* ptrBook2 = &Book2;
// 输出书籍信息,传递指针
printBookInfo(ptrBook1);
printBookInfo(ptrBook2);
return 0;
}
结构体与类的区别
在 C++ 中,struct 和 class 本质上非常相似,唯一的区别在于默认的访问权限:
struct
默认的成员和继承是public
。class
默认的成员和继承是private
。
可以将 struct
当作一种简化形式的 class
,适合用于没有太多复杂功能的简单数据封装
结构体与函数结合
struct Books {
string title;
string author;
string subject;
int book_id;
// 构造函数
Books(string t, string a, string s, int id)
: title(t), author(a), subject(s), book_id(id) {}
void printInfo() const {
cout << "书籍标题: " << title << endl;
cout << "书籍作者: " << author << endl;
cout << "书籍类目: " << subject << endl;
cout << "书籍 ID: " << book_id << endl;
}
};
void printBookByRef(const Books& book) {
book.printInfo();
}
C++ vector容器
C++ 中的 vector 是一种序列容器,它允许你在运行时动态地插入和删除元素。
vector 是基于数组的数据结构,但它可以自动管理内存,这意味着你不需要手动分配和释放内存。
基本特性:
- 动态大小:
vector
的大小可以根据需要自动增长和缩小。 - 连续存储:
vector
中的元素在内存中是连续存储的,这使得访问元素非常快速。 - 可迭代:
vector
可以被迭代,你可以使用循环(如for
循环)来访问它的元素。 - 元素类型:
vector
可以存储任何类型的元素,包括内置类型、对象、指针等。
std::vector<int> myVector(5); // 创建一个包含 5 个整数的 vector,每个值都为默认值(0)
std::vector<int> myVector(5, 10); // 创建一个包含 5 个整数的 vector,每个值都为 10
std::vector<int> vec; // 默认初始化一个空的 vector
std::vector<int> vec2 = {1, 2, 3, 4}; // 初始化一个包含元素的 vector
#include <iostream>
#include <vector>
int main() {
// 创建一个空的整数向量
std::vector<int> myVector;
// 添加元素到向量中
myVector.push_back(3);
myVector.push_back(7);
myVector.push_back(11);
myVector.push_back(5);
// 访问向量中的元素并输出
std::cout << "Elements in the vector: ";
for (int element : myVector) {
std::cout << element << " ";
}
std::cout << std::endl;
// 访问向量中的第一个元素并输出
std::cout << "First element: " << myVector[0] << std::endl;
// 访问向量中的第二个元素并输出
std::cout << "Second element: " << myVector.at(1) << std::endl;
// 获取向量的大小并输出
std::cout << "Size of the vector: " << myVector.size() << std::endl;
// 删除向量中的第三个元素
myVector.erase(myVector.begin() + 2);
// 输出删除元素后的向量
std::cout << "Elements in the vector after erasing: ";
for (int element : myVector) {
std::cout << element << " ";
}
std::cout << std::endl;
// 清空向量并输出
myVector.clear();
std::cout << "Size of the vector after clearing: " << myVector.size() << std::endl;
return 0;
}
C++数据结构
1. 数组
2. 结构体
3. 类(class)
与struct类似,但功能更强大,支持继承、封装、多态等特性。
4. 链表(linked list)
一种动态数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
struct Node{
int data;//节点存储的数据
Node* next;//指向链表中下一个节点的指针
};
Node* head = nullptr;//头指针初始化,用于指向链表的第一个节点
Node* newNode = new Node{10, nullptr}//定义新指针newNode, 创建新节点
head = newNode;//插入新节点
5. 栈(stack)
栈是一种后进先出(LIFO, Last In First Out)的数据结构,常用于递归、深度优先搜索等场景。
只允许在栈顶进行插入和删除操作。
stack<int> s;
s.push(1);
s.push(2);
cout << s.top(); // 输出 2
s.pop();
6. 队列(queue)
队列是一种先进先出(FIFO, First In First Out)的数据结构,常用于广度优先搜索、任务调度等场景。插入操作在队尾进行,删除操作在队头进行。
queue<int> q;
q.push(1);
q.push(2);
cout << q.front(); // 输出 1
q.pop();
7. 双端序列(deque)
双端队列允许在两端进行插入和删除操作,是栈和队列的结合体。
deque<int> dq;
dq.push_back(1);
dq.push_front(2);
cout << dq.front(); // 输出 2
dq.pop_front();
8. 哈希表(Hash Table)
哈希表是一种通过键值对存储数据的数据结构,支持快速查找、插入和删除操作。C++ 中的 unordered_map
是哈希表的实现。
unordered_map<string, int> hashTable;
hashTable["apple"] = 10;
cout << hashTable["apple"]; // 输出 10
9. 映射(map)
map
是一种有序的键值对容器,底层实现是红黑树。与 unordered_map
不同,它保证键的顺序,查找、插入和删除的时间复杂度为 O(log n)
map<string, int> myMap;
myMap["apple"] = 10;
cout << myMap["apple"]; // 输出 10
10. 集合(set)
set
是一种用于存储唯一元素的有序集合,底层同样使用红黑树实现。它保证元素不重复且有序。
set<int> s;
s.insert(1);
s.insert(2);
cout << *s.begin(); // 输出 1
11. 动态数组(vector)