c++ day1

发布时间 2023-07-05 22:09:32作者: 芜湖大厨师

跟着数据结构,算法与应用 c++语言描述来学习

本书第一周计划回顾c++的基础知识

本人只是记录自己认为要去记录的一些资料

想要系统的学习还是需要去啃书

1

template<class T> 是C++中用于定义模板的语法结构。它表明接下来的代码是一个模板,并且模板参数名为T,它可以是任意合法的C++类型。

通过使用模板,您可以编写通用的代码,使其能够适用于不同的数据类型。模板在C++中广泛用于实现泛型编程,它允许您编写能够适用于多种数据类型的函数、类和数据结构。

在使用模板时,T是一个占位符,它代表着实际的数据类型。您可以在模板定义中使用T来声明变量、参数、返回类型等,并在实际使用时用具体的类型替代T

下面是一些例子

 1  //1class 或 typename:
 2 template<class T>
 3 void print(T value) {
 4     std::cout << value << std::endl;
 5 }
 6 
 7 int main() {
 8     print<int>(42); // 打印整数
 9     print<std::string>("Hello"); // 打印字符串
10     return 0;
11 }
//2 int, bool, char 等基本类型:
template<int N>
void printNTimes(const std::string& value) {
    for (int i = 0; i < N; ++i) {
        std::cout << value << std::endl;
    }
}

int main() {
    printNTimes<5>("Hello"); // 打印 "Hello" 5次
    return 0;
}
 1 //3 模板参数类型:
 2 template<class T>
 3 struct MyContainer {
 4     T value;
 5 };
 6 
 7 template<template<class> class Container>
 8 void printValue(const Container<int>& container) {
 9     std::cout << container.value << std::endl;
10 }
11 
12 int main() {
13     MyContainer<int> container{42};
14     printValue(container); // 打印 42
15     return 0;
16 }
// 4 非类型参数
template<int Size>
void printArray(const int (&arr)[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); // 打印数组的元素
    return 0;
}

这只是列举了一些而已

2 c++是如何处理异常的

在C++中,异常处理是一种机制,用于处理程序中的异常情况,例如运行时错误或意外情况。C++使用trycatchthrow关键字来实现异常处理。

以下是异常处理的基本步骤:

  1. try 块:在try块中编写可能抛出异常的代码。如果在try块中的某个地方发生异常,程序将跳转到catch块。

  2. throw 语句:在try块中,如果遇到异常情况,可以使用throw语句抛出一个异常。throw语句通常抛出一个异常对象,该对象可以是C++内置类型或自定义的异常类的实例。

  3. catch 块:在catch块中定义异常处理程序。catch块后面跟着一个括号,其中指定异常类型,表示它可以处理哪种类型的异常。当异常被抛出时,程序将查找与抛出的异常类型匹配的catch块,并执行相应的处理代码。

  下面是一个简单的示例

 1 #include <iostream>
 2 
 3 int main() {
 4     try {
 5         // 可能抛出异常的代码
 6         int divisor = 0;
 7         int result = 10 / divisor;
 8     } catch (const std::exception& e) {
 9         // 异常处理代码
10         std::cout << "Exception caught: " << e.what() << std::endl;
11     }
12 
13     return 0;
14 }

在这个例子中,我们尝试将整数10除以0,这是一个会导致运行时错误的操作。程序在运行时抛出一个异常,然后进入catch块。catch块中的std::exception参数可以捕获各种异常类型,并输出相应的错误消息。

您还可以使用多个catch块来处理不同类型的异常,以执行不同的处理操作。捕获的catch块将按照它们在代码中出现的顺序进行匹配,所以将具体的异常类型的catch块放在前面,将通用的catch块放在后面是一个良好的实践。

3 理解了智能指针

C++ 提供了智能指针作为一种更安全和方便的动态内存管理工具。智能指针是一种包装了原始指针的对象,它们提供了自动管理动态分配内存的能力,从而避免了手动调用 delete 运算符的需要,并减少了内存泄漏和悬挂指针等问题的风险。

C++ 标准库提供了三种主要的智能指针类型:

  1. std::unique_ptrstd::unique_ptr 是独占所有权的智能指针,它确保只有一个指针可以管理特定的资源。当 std::unique_ptr 被销毁时,它将自动释放所管理的对象的内存。它不能被拷贝,但可以通过移动语义进行转移所有权。
std::unique_ptr<int> ptr = std::make_unique<int>(10);
  1. std::shared_ptrstd::shared_ptr 是共享所有权的智能指针,它允许多个指针共同管理同一个对象。当最后一个 std::shared_ptr 被销毁时,才会释放所管理的对象的内存。它使用引用计数来追踪对象的所有权。
std::shared_ptr<int> ptr1 = std::make_shared<int>(10); std::shared_ptr<int> ptr2 = ptr1; // 共享所有权
  1. std::weak_ptrstd::weak_ptr 是一种弱引用指针,它可以观测到由 std::shared_ptr 管理的对象,但不会增加引用计数。它可以用来避免循环引用和解决共享指针的悬挂指针问题。
std::shared_ptr<int> sharedPtr = std::make_shared<int>(10); std::weak_ptr<int> weakPtr = sharedPtr; // 弱引用

使用智能指针可以简化动态内存管理,并提供了更强大的内存安全性和方便性。智能指针会在合适的时机自动释放内存,避免了显式的 delete 操作,并减少了手动管理内存的错误。

与传统的裸指针相比,智能指针使用了析构函数和引用计数等机制来自动管理内存的释放。当最后一个指向某个对象的智能指针被销毁时,它会自动调用析构函数来释放所管理的内存。这种自动化的内存管理可以避免忘记释放内存或释放过早的问题,从而减少内存泄漏和悬挂指针的风险。

对于二维数组 我一直是直接 a[][n]这样来写 但是全书使用动分配来写二维数组 那么熟悉熟悉一下动态分配

要使用动态内存分配创建一个二维数组,可以使用指针的指针(双重指针)或者使用一维指针来模拟二维数组。下面分别介绍这两种方法。

方法一:使用指针的指针(双重指针)

 1 int rows = 3;
 2 int cols = 4;
 3 
 4 // 动态分配二维数组
 5 int** arr = new int*[rows];
 6 for (int i = 0; i < rows; i++) {
 7     arr[i] = new int[cols];
 8 }
 9 
10 // 访问和操作二维数组元素
11 arr[0][0] = 1;
12 arr[1][2] = 3;
13 
14 // 释放内存
15 for (int i = 0; i < rows; i++) {
16     delete[] arr[i];
17 }
18 delete[] arr;

这种方法使用双重指针 int**,首先在堆上分配一个指针数组,每个指针指向一个行数组。然后,通过对指针数组和行数组进行循环,可以访问和操作二维数组的元素。最后,需要逐行释放内存空间,再释放指针数组的内存空间。

方法二:使用一维指针模拟二维数组

 1 int rows = 3;
 2 int cols = 4;
 3 
 4 // 动态分配一维数组
 5 int* arr = new int[rows * cols];
 6 
 7 // 访问和操作二维数组元素
 8 arr[0 * cols + 0] = 1;
 9 arr[1 * cols + 2] = 3;
10 
11 // 释放内存
12 delete[] arr;

这种方法将二维数组用一维数组来表示,可以使用一维指针 int* 来动态分配内存。通过行数和列数,可以通过索引计算出对应元素在一维数组中的位置,并进行访问和操作。最后,只需要使用 delete[] 释放一维数组的内存空间。

 书中采用第一种方法
 1 template <class T >
 2 bool make2dArray ( T ** &x, int numberOfRows, int numberOfColumns ) {
 3     // create pointers for the rows
 4     x = new T * [numberOfRows];
 5     if ( x == NULL ) return false;
 6     // get memory for each row
 7     for ( int i = 0; i < numberOfRows; i++ ) {
 8         x[i] = new T [numberOfColumns];
 9         if ( x[i] == NULL ) return false;
10     }
11     return true;
12 }

下面是deleter代码

 1 bool delete2dArray(T ** &array, int n) {
 2     if (array == nullptr) {
 3         return false;
 4     }
 5     for (int i = 0; i < n; ++i) {
 6         delete[] array[i];
 7     }
 8     delete[] array;
 9     array = nullptr;
10     return true;
11 }