C++开发学习笔记3

C++ 中枚举的使用

在C++中,枚举常量(Enumeration Constants)是一种定义命名常量的方式。枚举类型允许我们为一组相关的常量赋予有意义的名称,并将它们作为一个独立的类型来使用。

以下是定义和使用枚举常量的示例:

cpp 复制代码
enum Color {
    RED,
    GREEN,
    BLUE
};

int main() {
    Color myColor = RED;
    if (myColor == GREEN) {
        // 执行GREEN相关的逻辑
    } else if (myColor == BLUE) {
        // 执行BLUE相关的逻辑
    } else {
        // 执行默认逻辑(RED)
    }
    
    return 0;
}

在上述代码中,我们定义了一个名为Color的枚举类型,并声明了三个枚举常量REDGREENBLUE。这些常量都属于Color类型,它们实际上是整数值,默认从0开始递增。

main()函数中,我们创建了一个myColor变量,并将其初始化为RED枚举常量。我们可以使用if语句来检查myColor的值,根据不同的情况执行相应的逻辑。

需要注意的是,枚举常量是命名的整数值,并且可以通过名称进行比较和赋值操作。此外,我们也可以指定枚举常量的具体整数值,例如:

cpp 复制代码
enum Status {
    OK = 200,
    NOT_FOUND = 404,
    INTERNAL_ERROR = 500
};

在这个示例中,我们为枚举常量OKNOT_FOUNDINTERNAL_ERROR分别指定了整数值200、404和500。这样做可以在需要时将枚举常量与特定的整数值相关联。

总之,C++中的枚举常量提供了一种定义有意义的命名常量的方式,并使得代码更易读、更具可维护性。

C++ 中程序睡眠

在 C++ 中,可以使用 <thread> 头文件中的 sleep_for() 函数来实现睡眠功能。sleep_for() 函数接受一个时间段作为参数,指定程序需要休眠的时间长度。

下面是一个示例代码,展示了如何在 C++ 中使用 sleep_for() 函数实现睡眠功能:

cpp 复制代码
#include <iostream>
#include <thread> // 包含 <thread> 头文件

int main() {
    std::cout << "开始执行程序" << std::endl;

    // 休眠 2 秒
    std::this_thread::sleep_for(std::chrono::seconds(2));

    std::cout << "休眠结束,继续执行程序" << std::endl;

    return 0;
}

在上面的示例中,我们通过调用 std::this_thread::sleep_for() 函数并传入 `std::chrono::seconds

C++ 如何释放内存

在C++中,可以使用以下几种方法来释放动态分配的内存:

  1. 使用delete释放单个对象的内存:

    cpp 复制代码
    int* ptr = new int;  // 动态分配一个整数对象的内存
    // 使用分配的内存
    delete ptr;  // 释放内存
  2. 使用delete[]释放数组的内存:

    cpp 复制代码
    int* arr = new int[5];  // 动态分配一个整数数组的内存
    // 使用分配的内存
    delete[] arr;  // 释放内存
  3. 使用free函数释放通过malloccallocrealloc分配的内存:

    cpp 复制代码
    int* ptr = (int*)malloc(sizeof(int));  // 分配内存
    // 使用分配的内存
    free(ptr);  // 释放内存

需要注意的是:

  • 动态分配的内存必须由相应的释放函数进行释放,以避免内存泄漏。
  • 在释放内存之后,不要再访问已释放的内存块,以免发生未定义行为。
  • 删除或释放空指针是安全的,因此在释放内存之后最好将指针设置为nullptr,以防止误用。

另外,使用智能指针(如std::unique_ptrstd::shared_ptr)等现代C++特性可以更方便地管理内存,并避免手动释放内存的问题。这些智能指针会在不再需要时自动释放它们持有的内存。

C++ 参数传递方式

在C++中,有两种主要的参数传递方式:值传递和引用传递。

  1. 值传递:
    • 值传递是将实际参数的副本传递给函数或方法。
    • 在值传递中,函数或方法使用参数的副本进行操作,对原始参数没有影响。
    • 在函数或方法内部,会为参数的副本分配新的内存空间,并在函数或方法调用结束后释放该空间。
    • 值传递不会改变原始参数的值。

示例代码:

cpp 复制代码
void modifyValue(int x) {
    x = 10;  // 修改参数的副本
}

int main() {
    int num = 5;
    modifyValue(num);  // 值传递
    // num 的值仍然是 5,没有被修改
    return 0;
}
  1. 引用传递:
    • 引用传递是将实际参数的引用传递给函数或方法。
    • 在引用传递中,函数或方法使用参数的引用直接对原始参数进行操作。
    • 在函数或方法内部,没有为参数分配新的内存空间,它直接引用了原始参数的内存空间。
    • 引用传递可以改变原始参数的值。

示例代码:

cpp 复制代码
void modifyValue(int& x) {
    x = 10;  // 直接修改原始参数
}

int main() {
    int num = 5;
    modifyValue(num);  // 引用传递
    // num 的值被修改为 10
    return 0;
}

需要注意的是,无论是值传递还是引用传递,都会在函数或方法调用结束后自动释放传递的参数。但是,在引用传递中,由于直接引用了原始参数的内存空间,所以可以对其进行修改并影响原始参数的值。而值传递只是操作了参数的副本,不会改变原始参数的值。

关于析构函数的特性

C++ 的析构函数(Destructor)是一种特殊的成员函数,用于在对象被销毁时执行清理工作。它的实现原理如下:

  1. 析构函数的命名规则是在类名前加上一个波浪线(~),后接类名,例如~ClassName
  2. 析构函数没有参数,也不能被重载,每个类只能有一个析构函数。
  3. 当对象被销毁时(例如离开作用域、delete 操作符释放动态分配的内存),编译器会自动调用对象的析构函数。
  4. 对象的析构函数按照创建对象的顺序逆序调用,即最后创建的对象先调用析构函数。
  5. 析构函数可以显式定义,也可以使用编译器生成的默认析构函数。
  6. 如果显式定义了析构函数,编译器就不会生成默认的析构函数。
  7. 在析构函数中,可以执行必要的清理工作,如释放动态分配的内存、关闭打开的文件、释放资源等。

在程序运行过程中,当对象即将被销毁时,编译器会自动插入对析构函数的调用。这样可以确保在对象生命周期结束时进行清理操作,避免资源泄漏和内存泄漏问题。

需要注意的是,在有继承关系的类中,基类的析构函数应该声明为虚函数,以便子类能够正确调用其自身的析构函数。这是因为在使用基类指针或引用指向派生类对象时,如果基类的析构函数不是虚函数,那么就无法通过基类指针或引用来调用派生类的析构函数,从而导致资源无法正确释放。

总结:C++ 的析构函数通过编译器自动调用,在对象销毁时执行必要的清理工作,它的实现原理包括命名规则、调用顺序等。合理使用析构函数可以确保资源的正确释放,避免内存泄漏和资源泄漏问题的发生。

C++ 的析构函数实际上是由编译器自动生成和调用的,其实现原理如下:

  1. 自动调用:当对象的生命周期结束时,编译器会自动调用适当的析构函数。这可以发生在以下几种情况下:

    • 对象离开其作用域:当对象在函数中定义,并且超出了其作用域范围时,编译器会自动调用该对象的析构函数。
    • 动态分配内存的对象被释放:如果通过new关键字动态创建了对象并进行了内存分配,在使用delete操作符释放内存时,编译器会自动调用该对象的析构函数。
    • 对象被销毁:当一个对象作为另一个对象的成员时,当包含它的对象被销毁时,编译器会自动调用该成员对象的析构函数。
  2. 生成默认析构函数:如果没有显式定义析构函数,编译器会自动生成一个默认的析构函数。默认析构函数的实现为空,即不执行任何操作。

  3. 显式定义析构函数:在需要进行一些清理工作的情况下,可以显式地在类中定义析构函数。在析构函数的定义中,可以编写所需的清理代码,例如释放动态分配的内存、关闭文件、释放资源等。

  4. 调用顺序:在具有继承关系的类中,当派生类对象被销毁时,会先自动调用派生类的析构函数,然后再调用基类的析构函数。这样可以确保在对象层次结构中的每个类都能够执行必要的清理工作,并按照正确的顺序进行。

需要注意的是,如果在基类中将析构函数声明为虚函数(使用virtual关键字),则在通过基类指针或引用删除派生类对象时,会调用正确的析构函数。这是因为虚析构函数允许动态绑定,在运行时选择正确的析构函数。

总结:C++ 的析构函数实际上是由编译器自动生成和调用的,它的实现原理涉及自动调用、默认生成、显式定义和调用顺序等方面。合理使用析构函数可以确保资源的正确释放,避免内存泄漏和资源泄漏问题的发生。

C++ 全局变量

C++ 中的全局变量是在函数外部定义的变量,可以在程序的任何地方使用。全局变量在整个程序中都是可见的,可以被多个函数或模块使用。

在C++中,全局变量的声明通常放在头文件中,并且在源文件中进行定义和初始化。全局变量可以有不同的存储类别(如 static、extern 等),它们决定了全局变量的作用域和生命周期。

以下是一个示例:

cpp 复制代码
// 头文件 global_var.h
extern int globalVar; // 声明全局变量

// 源文件 main.cpp
#include "global_var.h"

int globalVar = 10; // 定义并初始化全局变量

void func()
{
    // 在这里可以使用全局变量 globalVar
}

int main()
{
    // 在这里也可以使用全局变量 globalVar
    return 0;
}

需要注意的是,全局变量的使用应该谨慎,因为它们具有全局作用域,可能会导致代码的可读性和维护性下降。过多地依赖全局变量可能会增加代码之间的耦合性,使程序难以理解和调试。因此,在设计程序时,应尽量避免过度使用全局变量。

相关推荐
huangkj-henan5 分钟前
DA217应用笔记
笔记
Young_202202026 分钟前
学习笔记——KMP
笔记·学习
娅娅梨10 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
兵哥工控15 分钟前
MFC工控项目实例二十九主对话框调用子对话框设定参数值
c++·mfc
我爱工作&工作love我22 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
行然梦实22 分钟前
学习日记_20241110_聚类方法(K-Means)
学习·kmeans·聚类
马船长28 分钟前
制作图片木马
学习
秀儿还能再秀39 分钟前
机器学习——简单线性回归、逻辑回归
笔记·python·学习·机器学习
WCF向光而行44 分钟前
Getting accurate time estimates from your tea(从您的团队获得准确的时间估计)
笔记·学习
娃娃丢没有坏心思1 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++