C++学习笔记四

发布于:2025-07-12 ⋅ 阅读:(20) ⋅ 点赞:(0)

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)


网站公告

今日签到

点亮在社区的每一天
去签到