【C++篇】C++类与对象深度解析(二):类的默认成员函数详解

news2024/12/28 5:52:50

文章目录

  • 【C++篇】C++类与对象深度解析(二)
    • 前言
      • 1. 类的默认成员函数
      • 2. 构造函数
        • 2.1 函数名与类名相同
        • 2.2 无返回值
        • 2.3 对象实例化时系统会自动调用
        • 2.4 构造函数可以重载
        • 2.5 默认构造函数的生成规则
        • 2.6 无参构造函数与全缺省构造函数的关系
        • 2.7 内置类型与自定义类型成员变量的初始化
      • 示例代码梳理
      • 3. 析构函数
        • 1. 析构函数名
        • 2. 无参数无返回值
        • 3. 一个类只能有一个析构函数
        • 4. 对象生命周期结束时,系统会自动调用析构函数
        • 5. 跟构造函数类似,编译器自动生成的析构函数对内置类型成员不做处理
        • 6. 显式写析构函数情况
        • 7. 析构函数可以不写的情况
        • 8. 一个局部域的多个对象,C++规定后定义的先析构
      • 示例代码梳理
      • 使用C++实现的Stack解决括号匹配问题
      • 4. 拷贝构造函数
        • 1. 拷贝构造函数是构造函数的一个重载
        • 2. 拷贝构造函数的第一个参数必须是类类型对象的引用
        • 3. C++规定自定义类型对象进行拷贝时必须调用拷贝构造函数
        • 4. 若未显式定义拷贝构造函数,编译器会自动生成
        • 5. 编译器自动生成的拷贝构造函数对内置类型和自定义类型的处理
        • 6. 拷贝构造函数在传值返回时的行为
      • 示例代码梳理
    • 写在最后

【C++篇】C++类与对象深度解析(二)

前言

💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!

👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力!
🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对C++感兴趣的朋友,让我们一起进步!

接上篇C++类与对象深度解析(一):从抽象到实践的全面入门指南

在上篇文章《C++类与对象深度解析(一):从抽象到实践的全面入门指南》,我们初步探讨了C++类的基本概念和核心特性。在这篇文章中,我们将深入理解C++中的默认成员函数,这些函数是类的基石,理解它们对于掌握C++面向对象编程至关重要。本篇将侧重于解析构造函数、析构函数及拷贝构造函数,这些都是C++自动为类生成的成员函数,它们在类对象的生命周期管理中扮演着关键角色。

1. 类的默认成员函数

在C++中,默认成员函数是指用户没有显式实现,而由编译器自动生成的成员函数。一个类在没有显式定义特定成员函数的情况下,编译器会自动生成以下6个默认成员函数。理解这些默认成员函数的行为和作用是掌握C++类机制的基础。

在这里插入图片描述

补充:

移动构造函数移动赋值运算符是在C++11引入的,用于优化资源的移动操作,减少不必要的拷贝。如果用户没有显式定义,编译器会自动生成这两个函数。

  • 行为:默认的移动构造函数和移动赋值运算符会将资源从一个对象“移动”到另一个对象,源对象的资源会被“剥离”。
  • 需求:对于那些管理动态资源的类,显式定义这些函数可以显著提高程序的效率,避免冗余的资源分配和释放操作。

本篇详细介绍前三个成员函数


2. 构造函数

构造函数是用于初始化对象的特殊成员函数。虽然名称为“构造”,但它的主要任务是初始化对象的成员变量,而不是为对象分配内存。构造函数的使用对于确保对象在创建时处于有效状态至关重要。

2.1 函数名与类名相同

构造函数的名字必须与类名相同。这是C++的语法要求

  • 解释:构造函数的名字与类名相同,使得编译器能够识别它是用于初始化对象的函数,而不是普通的成员函数。
  • 示例
    class MyClass {
    public:
        MyClass() { /* 构造函数体 */ }
    };
    
2.2 无返回值

构造函数没有返回值,甚至不能声明void。这是C++语言规定的,构造函数的唯一目的是初始化对象,因此不需要返回任何值。

  • 解释:构造函数的任务是初始化对象,而不是返回数据。返回值的存在会违背构造函数的设计目的。
  • 示例
    class MyClass {
    public:
        MyClass() { /* 构造函数体,无返回值 */ }
    };
    
2.3 对象实例化时系统会自动调用

构造函数在对象实例化时自动调用。开发者不需要显式调用构造函数,编译器会在对象创建时自动执行它。

  • 解释:构造函数的自动调用确保了对象在创建时立即处于有效状态。无论对象是作为局部变量、全局变量还是动态分配的变量,构造函数都会在创建时运行。
  • 示例
    MyClass obj; // 调用构造函数
    
2.4 构造函数可以重载

构造函数可以重载,即同一个类中可以有多个构造函数,它们的参数列表必须不同。这允许对象在创建时根据不同的需求进行不同的初始化。

  • 解释:通过构造函数的重载,可以灵活地初始化对象。例如,一个类可以有无参构造函数和带参构造函数,以满足不同的初始化需求。
  • 示例
    class MyClass {
    public:
        MyClass() { /* 无参构造函数 */ }
        MyClass(int x) { /* 带参构造函数 */ }
    };
    
2.5 默认构造函数的生成规则

如果类中没有显式定义构造函数,编译器会自动生成一个无参的默认构造函数。但一旦用户定义了任何构造函数,编译器就不再生成默认构造函数。

  • 解释:默认构造函数提供了一个基本的初始化方式。如果用户定义了其他形式的构造函数(如带参数的),编译器认为用户不再需要默认构造函数,因此不会自动生成。
  • 示例
    class MyClass {
        // 没有显式定义构造函数,编译器会生成默认的无参构造函数
    };
    MyClass obj; // 调用默认构造函数
    
2.6 无参构造函数与全缺省构造函数的关系

无参构造函数、全缺省构造函数、默认生成的构造函数不能同时存在。如果定义了无参构造函数或全缺省构造函数,编译器将不会再生成默认构造函数。

  • 解释:这三种构造函数提供了相似的功能,即初始化对象而不需要显式提供参数。为了避免冲突,它们只能存在其中之一。
  • 示例
    class MyClass {
    public:
        MyClass() { /* 无参构造函数 */ }
        // MyClass(int x = 0) { /* 全缺省构造函数,不能与无参构造函数同时存在 */ }
    };
    

注意:无参构造函数、全缺省构造函数、编译器自动默认生成的构造函数全都叫默认构造函数!!!总结来说,可以不传参的就是默认构造函数,这三个不能同时存在,但是默认构造函数可以和带参的构造函数同时存在(即上文所说的函数重载),例如半缺省、没有缺省值等的普通构造函数。

有点绕,多品读一下😊

示例如下:

#include <iostream>
using namespace std;

class MyClass {
public:
    // 全缺省构造函数,即默认构造函数
    MyClass(int x = 10, int y = 20) {
        cout << "Called MyClass(int x = 10, int y = 20)" << endl;
        cout << "x = " << x << ", y = " << y << endl;
    }

    // 普通带参构造函数(没有缺省值)
    MyClass(double z) {
        cout << "Called MyClass(double z)" << endl;
        cout << "z = " << z << endl;
    }
};

int main() {
    MyClass obj1;           // 调用全缺省构造函数
    MyClass obj2(100);      // 调用全缺省构造函数,因为100是int类型
    MyClass obj3(3.14);     // 调用普通的带参构造函数
    return 0;
}
2.7 内置类型与自定义类型成员变量的初始化

如果是编译器自动生成的默认构造函数对内置类型成员变量的初始化没有要求,其值不确定。对于自定义类型的成员变量,编译器会调用它们的默认构造函数进行初始化。

  • 解释:内置类型(如intchar)的成员变量如果没有显式初始化,其值可能是未定义的。自定义类型的成员变量则必须通过其默认构造函数初始化。
  • 示例(这里是初始化列表,在这个系列的之后博客会讲到)
    class MyClass {
    public:
        MyClass() : _value(0) { /* 初始化内置类型成员变量 */ }
    private:
        int _value;
        std::string _name;// 自动调用std::string的默认构造函数
    }:
    
    

示例代码梳理

以下是展示上述特点的详细代码示例:

这里只是为了方便写的示例哈,如前文所述,无参和全缺省的默认构造函数只能存在一种

#include<iostream>
using namespace std;

class Date {
public:
    // 1. 无参构造函数
    Date() {
        _year = 1;
        _month = 1;
        _day = 1;
    }

    // 2. 带参构造函数
    Date(int year, int month, int day) {
        _year = year;
        _month = month;
        _day = day;
    }

    // 3. 全缺省构造函数
    Date(int year = 1, int month = 1, int day = 1) {
        _year = year;
        _month = month;
        _day = day;
    }

    void Print() {
        cout << _year << "/" << _month << "/" << _day << endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main() {
    // 调用无参构造函数
    Date d1;

    // 调用带参构造函数
    Date d2(2025, 1, 1);

    // 调用全缺省构造函数
    Date d3;

    d1.Print();
    d2.Print();

    return 0;
}

通过这个详细的解析和示例代码,我们可以清晰地理解C++类的默认成员函数和构造函数的特点及其作用。这样,开发者可以根据具体需求灵活地使用和自定义这些函数,以便更好地控制对象的生命周期和资源管理。


3. 析构函数

析构函数是与构造函数功能相反的一个函数,它用于在对象生命周期结束时释放资源。C++中规定,析构函数会在对象销毁时自动调用,以完成对象中资源的清理工作。这一特性使得C++能够有效地管理内存和其他资源,防止资源泄漏。

1. 析构函数名

析构函数的名称是类名的前面加上一个“~”符号,这是C++语法中的规定。它用于明确表示该函数是析构函数。

  • 解释:析构函数的名字与类名相同,但在前面加上“~”符号,这使得编译器能够识别这是一个析构函数。
  • 示例
    class MyClass {
    public:
        ~MyClass() {
            // 析构函数体
        }
    };
    
2. 无参数无返回值

析构函数不接受任何参数,也没有返回值。它的唯一任务是清理对象的资源。

  • 解释:由于析构函数是系统自动调用的,因此它不能有参数,也不需要返回任何值。
  • 示例
    class MyClass {
    public:
        ~MyClass() {
            // 无参数,无返回值
        }
    };
    
3. 一个类只能有一个析构函数

每个类只能定义一个析构函数。如果类中没有显式定义析构函数,系统会自动生成一个默认的析构函数。

  • 解释:C++规定,一个类只能有一个析构函数,因为一个对象只能在生命周期结束时被销毁一次。
  • 示例
    class MyClass {
    public:
        ~MyClass() {
            // 只能有一个析构函数
        }
    };
    
4. 对象生命周期结束时,系统会自动调用析构函数

当一个对象的生命周期结束(如对象超出作用域或显式删除对象)时,系统会自动调用析构函数来清理资源。

  • 解释:析构函数的自动调用确保了对象在被销毁时可以正确地释放资源,防止资源泄漏。
  • 示例
    class MyClass {
    public:
        ~MyClass() {
            cout << "Object is being destroyed" << endl;
        }
    };
    
    int main() {
        MyClass obj; // 当obj超出作用域时,系统会自动调用析构函数
        return 0;
    }
    
5. 跟构造函数类似,编译器自动生成的析构函数对内置类型成员不做处理

如果类中没有显式定义析构函数,编译器会自动生成一个默认析构函数。这个默认析构函数对内置类型的成员变量不做任何处理。

  • 解释:对于内置类型(如intchar等),默认析构函数不需要释放资源。但对于自定义类型的成员,编译器生成的析构函数会调用这些成员的析构函数。
  • 示例
    class MyClass {
    private:
        int _value;
    public:
        // 编译器自动生成的析构函数对内置类型不做处理
    };
    
6. 显式写析构函数情况

如果显式定义了析构函数,对于自定义类型的成员变量,它们的析构函数也会被自动调用。

  • 解释:当显式定义析构函数时,C++确保所有自定义类型的成员都会在对象销毁时调用其析构函数,正确地释放资源。
  • 示例
    class MyClass {
    private:
        std::string _name; // 自定义类型成员
    public:
        ~MyClass() {
            // 自定义类型的成员变量会自动调用其析构函数
        }
    };
    
7. 析构函数可以不写的情况

如果类中没有动态分配的资源或其他需要手动释放的资源,可以不显式定义析构函数,使用编译器生成的默认析构函数。

  • 解释:对于没有动态资源的类,编译器生成的析构函数已经足够使用,不需要额外的析构逻辑。
  • 示例
    class MyClass {
    private:
        int _value; // 没有动态资源,编译器生成的析构函数已足够
    };
    
8. 一个局部域的多个对象,C++规定后定义的先析构

在一个局部作用域内定义的多个对象,C++规定后定义的对象会先调用析构函数。

  • 解释:这一规则确保了对象按照“后进先出”的顺序销毁,符合栈的逻辑。
  • 示例
    class MyClass {
    public:
        ~MyClass() {
            cout << "Destructor called" << endl;
        }
    };
    
    int main() {
        MyClass obj1;
        MyClass obj2;
        // obj2会在obj1之前被销毁
        return 0;
    }
    

示例代码梳理

以下是完整展示上述析构函数特点的详细代码示例:

#include<iostream>
using namespace std;

typedef int STDataType;

class Stack {
public:
    Stack(int n = 4) {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        if (_a == nullptr) {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = n;
        _top = 0;
    }

    ~Stack() { // 自定义析构函数,释放动态分配的内存
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _top = _capacity = 0;
    }

private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};

// 两个Stack实现队列
class MyQueue {
public:
    MyQueue() : pushst(), popst() {}

    // 默认析构函数自动调用两个Stack成员的析构函数
    // 显式定义的析构函数,也会自动调用Stack成员的析构函数
    /*~MyQueue() {}*/

private:
    Stack pushst;
    Stack popst;
};

int main() {
    Stack st;

    MyQueue mq; // MyQueue的析构函数会自动调用pushst和popst的析构函数

    return 0;
}

使用C++实现的Stack解决括号匹配问题

#include<iostream>
using namespace std;

bool isValid(const char* s) {
    Stack st;

    while (*s) {
        if (*s == '[' || *s == '(' || *s == '{') {
            st.Push(*s);
        } else {
            if (st.Empty()) {
                return false;
            }

            char top = st.Top();
            st.Pop();

            if ((*s == ']' && top != '[') ||
                (*s == '}' && top != '{') ||
                (*s == ')' && top != '(')) {
                return false;
            }
        }
        ++s;
    }

    return st.Empty(); // 确保所有括号都匹配
}

int main() {
    cout << isValid("[()][]") << endl; // 输出1(true)
    cout << isValid("[(])[]") << endl; // 输出0(false)

    return 0;
}

通过上面的代码,我们可以清楚地看到,C++的构造函数和析构函数帮助管理资源,避免了手动调用初始化和清理函数的麻烦。C++的这种自动化特性极大地简化了资源管理,尤其是在动态内存管理的场景下。


4. 拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它用于通过已有对象来创建一个新的对象。在C++中,如果构造函数的第一个参数是自身类类型的引用,并且任何额外的参数都有默认值,那么这个构造函数就是拷贝构造函数。

1. 拷贝构造函数是构造函数的一个重载

拷贝构造函数实际上是构造函数的一种重载形式,它与普通构造函数的区别在于其参数类型和目的。

  • 解释:拷贝构造函数的定义方式与普通构造函数类似,但它的第一个参数必须是同类对象的引用,用于创建新对象时进行对象的复制
  • 示例
    class MyClass {
    public:
        MyClass(int value) {
    _value = value;
    } { }  // 普通构造函数
    
        MyClass(const MyClass& other) {        // 拷贝构造函数
            _value = other._value;
        }
    
    private:
        int _value;
    };
    
2. 拷贝构造函数的第一个参数必须是类类型对象的引用

拷贝构造函数的第一个参数必须是类类型的引用,不能是传值,因为传值会导致编译器不断调用拷贝构造函数,最终引发无限递归,导致编译错误。

在这里插入图片描述

  • 解释:通过引用传递对象可以避免不必要的拷贝操作,并且能够直接访问原对象的内容。这种设计是为了防止调用拷贝构造函数时再次触发拷贝,从而引发无限递归。
  • 示例
    class MyClass {
    public:
        MyClass(const MyClass& other) {  // 正确:使用引用作为参数
            _value = other._value;
        }
    
        // MyClass(MyClass other) {       // 错误:传值会导致无限递归
        //     _value = other._value;
        // }
    
    private:
        int _value;
    };
    
3. C++规定自定义类型对象进行拷贝时必须调用拷贝构造函数

在C++中,当自定义类型对象需要被拷贝时(如传值传参或返回对象时),系统会自动调用拷贝构造函数。这是C++管理对象生命周期的一个基本机制。

  • 解释:无论是通过值传递一个对象,还是从函数中返回一个对象,C++都会调用拷贝构造函数来创建新的对象副本。这确保了对象能够被正确地拷贝和初始化。
  • 示例
    void Func(MyClass obj) {
        // 传值调用,自动调用拷贝构造函数
    }
    
    MyClass ReturnObject() {
        MyClass temp(10);
        return temp;  // 返回对象时,自动调用拷贝构造函数
    }
    
    int main() {
        MyClass obj1(10);
        MyClass obj2 = obj1;  // 调用拷贝构造函数
        Func(obj1);           // 调用拷贝构造函数
        MyClass obj3 = ReturnObject();  // 调用拷贝构造函数
        return 0;
    }
    
4. 若未显式定义拷贝构造函数,编译器会自动生成

如果类中没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。这个默认的拷贝构造函数会对内置类型成员变量进行浅拷贝,对自定义类型成员变量调用它们的拷贝构造函数。

  • 解释:编译器生成的默认拷贝构造函数能够满足大部分情况下的需求,尤其是对于没有指针成员或动态资源的类。然而,对于涉及动态分配的资源,浅拷贝不合适,需要自定义拷贝构造函数来实现深拷贝。(如下会讲)
  • 示例
    class SimpleClass {
    public:
        int _value;
    
        // 未显式定义拷贝构造函数,编译器会生成默认的拷贝构造函数
    };
    
    int main() {
        SimpleClass obj1;
        obj1._value = 42;
        SimpleClass obj2 = obj1;  // 自动生成的拷贝构造函数
        return 0;
    }
    
5. 编译器自动生成的拷贝构造函数对内置类型和自定义类型的处理

如果类成员全部是内置类型(如intchar),编译器自动生成的拷贝构造函数可以完成所需的拷贝,无需显式定义。然而,如果类成员包含指针或动态资源,编译器生成的浅拷贝可能不合适,需要自定义实现深拷贝。

  • 解释:浅拷贝只会复制指针的地址,而不会复制指针所指向的数据。这在动态内存管理中可能导致多个对象共享同一块内存,从而引发资源释放时的冲突。因此,对于涉及动态内存的类,通常需要自定义深拷贝构造函数。
  • 示例
    class Stack {
    public:
        Stack(int size) {
            _data = new int[size];
            _size = size;
        }
    
        // 自定义拷贝构造函数,实现深拷贝
        Stack(const Stack& other) {
            _data = new int[other._size];//之后在内存管理会讲到
            _size = other._size;
            for (int i = 0; i < _size; ++i) {
                _data[i] = other._data[i];
            }
        }
    
        ~Stack() {
            delete[] _data;  // 析构函数释放资源
        }
    
    private:
        int* _data;
        int _size;
    };
    
6. 拷贝构造函数在传值返回时的行为

当通过传值返回一个对象时,会产生一个临时对象,系统会调用拷贝构造函数来完成对象的复制。然而,传引用返回不会调用拷贝构造函数,而是返回对象的引用。

  • 解释:在C++中,通过值返回对象时,编译器会调用拷贝构造函数来创建返回值的副本。如果通过引用返回对象,则没有拷贝发生。然而,引用返回需要确保返回的对象在函数结束后仍然存在,否则会导致悬空引用
  • 示例
    MyClass ReturnByValue() {
        MyClass temp(10);
        return temp;  // 调用拷贝构造函数,返回对象副本
    }
    
    MyClass& ReturnByReference() {
        static MyClass temp(10);  // 使用static,确保返回的引用有效
        return temp;  // 返回引用,不调用拷贝构造函数
    }
    
    int main() {
        MyClass obj1 = ReturnByValue();    // 调用拷贝构造函数
        MyClass& obj2 = ReturnByReference();  // 不调用拷贝构造函数
        return 0;
    }
    

示例代码梳理

以下是展示上述拷贝构造函数特点的详细代码示例:

#include<iostream>
using namespace std;

class Date {
public:
    Date(int year = 1, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}

    // 自定义拷贝构造函数
    Date(const Date& d) {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }

    void Print() const {
        cout << _year << "-" << _month << "-" << _day << endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

void Func1(Date d) {
    d.Print();
}

Date Func2() {
    Date tmp(2024, 7, 5);
    return tmp;  // 返回值传递,调用拷贝构造函数
}

int main() {
    Date d1(2024, 7, 5);

    Func1(d1);  // 传值传参,调用拷贝构造函数

    Date d2(d1);  // 显式调用拷贝构造函数
    d2.Print();

    Date d3 = d1;  // 另一种形式的拷贝构造
    d3.Print();

    Date ret = Func2();  // 调用拷贝构造函数
    ret.Print();

    return 0;
}

通过这些代码示例和解释,我们可以深入理解C++中拷贝构造函数的特性及其应用场景。这些知识点对编写高效、安全的C++代码至关重要,特别是在处理自定义类型和动态资源时,掌握拷贝构造函数的用法可以有效防止潜在的错误和资源泄漏。


写在最后

在编写C++代码时,理解类与对象的这些核心概念不仅能够提升你的编程水平,还能帮助你避免资源泄漏、内存管理错误等潜在的编程陷阱。通过掌握这些知识,你将在编写面向对象的C++代码时游刃有余。希望这篇博客能够成为你深入理解C++类与对象的重要参考,让你的C++编程之旅更加顺畅、高效。如果你对这篇博客内容有任何疑问或希望进一步探讨的地方,欢迎留言讨论,我们一起学习进步!


以上就是关于【C++篇】C++类与对象深度解析(二):类的默认成员函数详解的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2140710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

五、(JS)window中的定时器

一、为什么叫做window中的定时器 我们在全局中会用到一些函数&#xff0c;比如说alert函数&#xff0c;prompt函数&#xff0c;setTimeout等等 我们有在这里定义过这些函数吗&#xff1f;很明显没有。可见我们这些函数都是来自于window。 所以还可以写成window.setTimeout。…

Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解

目录 一、Linux软件包管理器 - yum&#xff08;ubuntu用apt代替yum&#xff09;1、Linux下安装软件的方式2、认识 yum3、查找软件包4、安装软件5、如何实现本地机器和云服务器之间的文件互传 二、Linux编辑器 - vim1、vim 的基本概念2、vim 下各模式的切换3、vim 命令模式各命令…

【Linux篇】TCP/IP协议(笔记)

目录 一、TCP/IP协议族体系结构 1. 数据链路层 &#xff08;1&#xff09;介绍 &#xff08;2&#xff09;常用协议 ① ARP协议&#xff08;Address Resolve Protocol&#xff0c;地址解析协议&#xff09; ② RARP协议&#xff08;Reverse Address Resolve Protocol&…

[Meachines] [Easy] Sauna DC域+AS-REP+TGT票证窃取+AutoLogon凭据+DCSync攻击

信息收集 IP AddressOpening Ports10.10.10.175TCP:53,80,88,135,139,389,445,464,593,3268,3269,5985 $ nmap -p- 10.10.10.175 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 53/tcp open domain? | fingerprint-strings: | DNSVersionBindReqTCP…

电容的不同材质对应的温度范围

电容的温度范围是指电容在不同温度下能够正常工作的范围。不同材质的电容具有不同的温度特性&#xff0c;以下是一些常见电容材质的温度范围。 C0G/NP0&#xff1a;这类电容具有非常稳定的电气性能&#xff0c;工作温度范围通常为-55℃至125℃。 X7R&#xff1a;X7R材质的电容…

2021高教社杯全国大学生数学建模竞赛C题 Python代码演示

目录 问题一1.1 根据附件 1&#xff0c;对 402 家供应商的供货特征进行量化分析计算供货特征数据标准化对正向指标归一化对负向指标归一化 1.2 建立反映保障企业生产重要性的数学模型熵权法熵权法-TOPSISAHP 1.3 在此基础上确定 50 家最重要的供应商&#xff0c;并在论文中列表…

软件工程毕业设计开题汇总

文章目录 &#x1f6a9; 1 前言1.1 选题注意事项1.1.1 难度怎么把控&#xff1f;1.1.2 题目名称怎么取&#xff1f; 1.2 开题选题推荐1.2.1 起因1.2.2 核心- 如何避坑(重中之重)1.2.3 怎么办呢&#xff1f; &#x1f6a9;2 选题概览&#x1f6a9; 3 项目概览题目1 : 大数据电商…

几个常见的非初等函数

在多个激励共同作用下,其响应恒等于每个激励单独引起的响应之和。这种现象称为线性现象。线性性质使得对这类现象的数学描述大为简化,它是线性系统理论的基础。 本篇博客将简单介绍以下几个常用的非初等函数。 rect 矩形函数(Rectangular Function)sinc 函数(Sinc Function)三…

“树”据结构:并查集从入门到AC

“树”据结构&#xff1a;并查集 前言算法设计代码示例优化相关文章 前言 在一组数据中&#xff0c;数据被分为了不同的集合&#xff0c;那么其中的集合往往可以用树形来表示。而区分集合&#xff0c;与查找集合的元素&#xff0c;就会成为核心的问题。并查集主要就是解决这类…

模特妙善:一位多才多艺的短视频达人,绽放新光彩

模特妙善&#xff0c;在当今多元化的网络时代&#xff0c;短视频已成为人们生活中不可或缺的一部分。而在这一领域中&#xff0c;有一位以其独特魅力和多才多艺而备受瞩目的达人&#xff0c;她就是妙善&#xff0c;本名高艳芳。 模特妙善&#xff0c;出生于山西省的著名景点——…

一款免费的AI搜索工具,提升您的搜索效率!

开搜AI是一款面向大众的、直达答案的AI搜索引擎&#xff0c;它能够为用户问题提供直接、精准的答案&#xff0c;并自动总结重点、生成大纲、思维导图并下载。 开搜AI功能特点 精准结果呈现&#xff1a;开搜AI能够直接呈现精准结果&#xff0c;省去用户翻阅多个的繁琐过程。信…

MyBatis 增删改查【后端 17】

MyBatis 增删改查 引言 MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射&#xff0c;将接口和 Java 的 POJOs (…

Adding Placement Constraints

步骤2&#xff1a;添加放置约束 探索一些设计层次结构&#xff0c;并开始放置逻辑元素以创建物理 约束。 1.从Flow Navigator中&#xff0c;选择Open Synthetic Design。综合设计可能 如果您直接进入此步骤&#xff0c;则已经打开。 合成网表打开&#xff0c;显示设备窗口。 2.…

Note091203_Outlook邮件撤回操作

Note091203_Outlook邮件撤回操作 如图所示&#xff1a; step1: 打开outlook step2&#xff1a; 点击已发送邮件&#xff0c;选中目标撤回邮件双击打开&#xff1b; step3&#xff1a; 点击图中2框所示&#xff0c;可看见撤回操作&#xff1b; 以上

Linux常用命令以及操作技巧

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明帮助命令常见的七个linux操作终端实用的技巧跟文件目录…

Leetcode—740. 删除并获得点数【中等】(unordered_map+set+sort)

2024每日刷题&#xff08;162&#xff09; Leetcode—740. 删除并获得点数 算法思想 实现代码 class Solution { public:int deleteAndEarn(vector<int>& nums) {unordered_map<int, int> freq;set<int> st;sort(nums.begin(), nums.end());int n num…

c++234继承

#include<iostream> using namespace std;//public 修饰的成员便俩个和方法都能使用 //protected&#xff1a;类的内部 在继承的子类中可使用 class Parents { public:int a;//名字 protected:int b;//密码 private:int c;//情人public:void printT(){cout << &quo…

关于wp网站出现的问题

问题1 问题1&#xff1a;如果出现这个界面的问题 说明是根目录的index.php编码出了问题&#xff0c;用备份的源文件退换一下即可。 问题2 问题2&#xff1a;如果出现页面错位现象&#xff0c;可能是某个WP插件引起的问题&#xff0c;这里需要逐步排查插件&#xff0c;或者你刚…

论文内容分类与检测系统源码分享

论文内容分类与检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

【二叉树进阶】二叉搜索树

目录 1. 二叉搜索树概念 2. 二叉搜索树的实现 2.1 创建二叉搜索树节点 2.2 创建实现二叉搜索树 2.3 二叉搜索树的查找 2.4 二叉搜索树的插入 2.5 二叉搜索树的删除 2.6 中序遍历 2.7 完整代码加测试 3. 二叉搜索树的应用 3.1 K模型&#xff1a; 3.2 KV模型&#xf…