<C++>二、类和对象-构造函数

news2024/11/27 1:39:15

1.类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。

空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

2bb2888a284f040286e4c4ce432e13ea.png

2.构造函数

构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

构造函数的目的就是为了创建对象的时候同时初始化。

其特征如下:

1.函数名与类名相同。
2.无返回值
3.对象实例化时编译器自动调用对应的构造函数。也就是说在创建对象的时候,就对成员变量进行初始化。

下面是一个Stack栈的类:


class Stack
{
public:
    //无参数构造函数 - 函数名与对象名相同
    Stack()
    {
        _a = nullptr;
        _size = _capacity = 0;
    }
    //带参数构造函数
    Stack(int n)
    {
        _a = (int*)malloc(sizeof(int) * n);
        if (nullptr == _a)
        {
            perror("malloc fail");
            exit(-1);
        }
        _capacity = n;
        _size = 0;
    }
    void Push(int x) {}
    void Destroy() {}
private:
    int* _a;
    int _size;
    int _capacity;
};
6eed38839bf21f69ace16a24e1d9bf3d.png
4.构造函数可以重载。(一个类可以有多个构造函数,也就是多种初始化方式)

//Date类举例
class Date
{
public:
    //无参构造函数
    Date()
    {
        _year = 1;
        _month = 1;
        _day = 1;
    }
    //带参构造函数
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
5c7f4e8d953771168b98db62260cc725.png

使用全缺省构造函数

在写构造函数的时候,推荐使用全缺省或者半缺省


class Date
{
public:
    //全缺省
    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;
};
982f189a5b82c5a671a3eab06a0d0279.png

全缺省构造函数不能和无参构造函数同时存在 - 出现歧义,编译器不知道调用哪个

5.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。 注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

为什么只能有一个默认构造函数? 因为调用的时候会发生歧义

不传参数就可以调用构造函数,一般建议每个类都提供一个默认构造函数

e90a1960b3dbb0b8ec350de5d54f9f1b.png
6.如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
938304bb86094e0c4aff5e98af2ebdee.png

为什么自动生成了默认构造函数,打印出来的变量还是随机值呢?

C++规定默认生成的构造函数:

1.内置类型成员不做处理
2.自定义类型的成员,会去调用自定义类型的类的构造函数。
注意:C++11中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

默认构造函数的场景:

比如用栈实现队列:


//Stack类
class Stack
{
public:
    //无参构造函数 - 函数名与对象名相同
    Stack()
    {
        cout << "Stack()" << endl;
        _a = nullptr;
        _size = _capacity = 0;
    }
    //带参数构造函数
    Stack(int n)
    {
        cout << "Stack()" << endl;
        _a = (int*)malloc(sizeof(int) * n);
        if (nullptr == _a)
        {
            perror("malloc fail");
            exit(-1);
        }
        _capacity = n;
        _size = 0;
    }
    void Push(int x) {}
    void Destroy() {}

    ~Stack()  //析构函数
    {
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _size = _capacity = 0;
    }
private:
    int* _a;
    int _size;
    int _capacity;
};
470730d0a0b989c37d0cd01cbc844484.png

可以看到MyQueue中没有构造函数,它会自动调用Stack类中的构造函数。

2.1构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。


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

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

2.2 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟 一个放在括号中的初始值或表达式。


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

private:
    int _year;
    int _month;
    int _day;
};
【注意】
1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2.类中包含以下成员,必须放在初始化列表位置进行初始化:
① 引用成员变量
② const成员变量
③ 自定义类型成员(且该类没有默认构造函数时)

class B
{
public:
    B(int)
        :_b(0)
    {
        cout << "B()" << endl;
    }
private:
    int _b;
};


class A
{
public:
    //1、哪个对象调用构造函数,初始化列表是它所有成员变量定义的位置
    //2、不管是否显示在初始化列表写,那么编译器每个变量都会初始化列表定义初始化
    //3、三个成员变量需要写初始化,一个是const变量,一个引用变量,一个自定义类型
    A()   //这是一个初始化列表
        :_x(1)
        ,_ref(_a1)
        , _a2(1)
        ,_bb(0)
    {
        _a1++;
        _a2--;
    }
private:
    int _a1 = 1;  // 声明
    int _a2 = 2;   //缺省值是在没有构造函数的时候,缺省值才有效 
    //const变量必须在定义的位置初始化,因为后面const变量就无法更改了
    //const int _x;   //加了这个const  编译器会报错,无法引用A的默认构造函数
    //const int _x = 1;  //C++11 可以这么给
    const int _x;
    int& _ref;
    B _bb;
};

int main()
{
    A aa;   // 对象整体的定义,每个成员什么时候定义呢?
    //必须给每个成员变量找一个定义的位置,不然像const这样的成员,没办法初始化

    return 0;
}
3.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量, 一定会先使用初始化列表初始化。

class Time
{
public:
    Time(int hour = 0)
        : _hour(hour)
    {
        cout << "Time()" << endl;
    }

private:
    int _hour;
};

class Date
{
public:
    Date(int day)
    {
    }

private:
    int _day;
    Time _t;    //调用Time的构造函数 ,打印Time();
};

int main()
{
    Date d(1);
}
4.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

class A
{
public:
    A(int a)
        : _a1(a), _a2(_a1)
    {
    }

    void Print()
    {
        cout << _a1 << " " << _a2 << endl;
    }

private:
    int _a2; //_a2先初始化,_a1在初始化   此时调用初始化列表,而_a1此时是随机值,所以_a2(_a1)后_a2为随机值
    int _a1;
};

int main()
{
    A aa(1);
    aa.Print();
}

/*     D
A.输出1 1
B.程序崩溃
C.编译不通过
D.输出1 随机值
*/

2.3 explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。


class Date
{
public:
    //1.单参构造函数,没有使用explicit修饰,具有类型转换作用
    Date(int year) : _year(year) {}
    
// 2,虽然有多个参数,但是创建对象时后两个参数可以不传递,没有使用explicit修饰,具有类型转换作用 - int转换为Date类
    Date(int year, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2022);

    d1 = 2023;
    //用一个整型变量给日期类型对象赋值
    //实际编译器背后会用2023构造一个无名对象,最后用无名对象给d1对象进行赋值
    return 0;
}

class Date
{
public:
    // explicit修饰构造函数,禁止类型转换
    explicit Date(int year, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) {}

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

int main()
{
    Date d1(2022);

    d1 = 2023;  //err 编译器报错,没有与这些操作数匹配的 "=" 运算符,操作数类型为:  Date = int
    return 0;
}

class Date
{
public:
    Date(int year) : _year(year), _month(1), _day(1) {}
    friend ostream& operator<<(ostream& out, const Date& d);
    // operator是重载运算符,后面了解
    Date& operator=(const Date& d)
    {
        if (this != &d)
        {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        return *this;
    }

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

ostream& operator<<(ostream& out, const Date& d)
{
    cout << d._year << " " << d._month << " " << d._day << endl;
    return out;
}

int main()
{
    Date d1(2022); // 构造函数

    d1 = 2023; // 隐式类型转换  构造+拷贝+优化->构造  有的编译器可能不会优化
    // 构造,调用Date(year),在拷贝调用的是operator
    // Date& ref = 10;  //err ref是类类型 不能引用10
    const Date& ref = 10; // 可以,隐式类型转换,10构造一个对象,临时对象具有常属性,所以const可以引用
    cout << ref << endl;   //10 1 1
    
    return 0;
}
用explicit修饰构造函数,将会禁止构造函数的隐式转换。

3.析构函数

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

其特征如下:

1.析构函数名是在类名前加上字符 ~。
2.无参数无返回值类型。
3.一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
4.对象生命周期结束时,C++编译系统系统自动调用析构函数。
5.关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定义类型成员调用它的析构函数。(跟构造函数类似)
6.如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类
7.析构函数的执行顺序是先创建的对象后析构,后创建的对象先析构

下面是几个可能需要使用析构函数的场景:

1.动态分配内存:当一个对象在堆上分配内存时,需要手动释放内存以避免内存泄漏。在对象的析构函数中释放分配的内存是一种常见的方法。

class MyClass {
public:
    MyClass() {
        data = new int[100];
    }
    ~MyClass() {
        delete[] data;
    }
private:
    int* data;
};
2.异常处理:如果在构造函数中发生了异常,那么对象可能没有完全初始化,因此析构函数应该只释放已经成功初始化的资源。

class MyClass {
public:
    MyClass() {
        // 可能会抛出异常
        data = new int[100];
        // 如果抛出异常,data指针将保持为nullptr
    }
    ~MyClass() {
        if (data != nullptr) {
            delete[] data;
        }
    }
private:
    int* data = nullptr;
};

4.拷贝构造函数

概念:

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

拷贝构造函数也是特殊的成员函数,其特征如下:

1.拷贝构造函数是构造函数的一个重载形式。
2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。

为什么需要拷贝构造呢?

因为编译器只能对内置类型进行直接拷贝,而自定义类型的拷贝,需要使用拷贝构造

09f30d90803d892972981dd6b3150368.png

Date类中的成员变量都是内置类型,编译器可以直接拷贝。而Stack栈中的a是指针,如果直接拷贝,st1和st2指向了同一块内存地址,当st2进行析构处理的时候,也就把st1的a也清理了,当st2push一个1,st1也会跟着push一个1,所以对于自定义不能直接拷贝。

为什么拷贝构造使用传值调用会发生无穷递归?


//传值调用
Date(Date d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
20ca443f4b000ecc142ab43dc5aed985.png

//正确的写法
class Date
{
public:
    Date(int year = 2023, 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()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2021, 2, 3);
    Date d2(d1);
    d2.Print();
    return 0;
}
817c4ed378097a9200851bfb078212cd.png
3.若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

默认生成拷贝构造和赋值重载:

a、内置类型完成浅拷贝/值拷贝--按byte一个一个拷贝
b、自定义类型,去调用这个成员拷贝构造/赋值重载

//自动生成构造拷贝函数对内置类型进行拷贝
class Date
{
public:
    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;
};
ec23b44cecffb8850a29fd63ca0e65d4.png
4.编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗? 当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?

//自动生成构造拷贝函数对自定义类型进行拷贝
typedef int DataType;
class Stack
{
public:
    Stack(size_t capacity = 10)
    {
        cout << "Stack(size_t capacity = 10)" << endl;

        _array = (DataType*)malloc(capacity * sizeof(DataType));
        if (nullptr == _array)
        {
            perror("malloc申请空间失败");
            exit(-1);
        }

        _size = 0;
        _capacity = capacity;
    }

    void Push(const DataType& data)
    {
        // CheckCapacity();
        _array[_size] = data;
        _size++;
    }

    ~Stack()
    {
        cout << "~Stack()" << endl;

        if (_array)
        {
            free(_array);
            _array = nullptr;
            _capacity = 0;
            _size = 0;
        }
    }

private:
    DataType* _array;
    size_t    _size;
    size_t    _capacity;
};
99a5c008f6222e789cc241f21b2a33ae.png

这里会发现上面的程序会崩溃掉?这里就需要我们以后讲的深拷贝去解决。

5d80bb2b8cb17c7270bcd10a63368624.png

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

5.拷贝构造函数典型调用场景:

a、使用已存在对象创建新对象

b、函数参数类型为类类型对象

c、函数返回值类型为类类型对象


typedef int DataType;
class Stack
{
public:
    Stack(size_t capacity = 10)
    {
        cout << "Stack(size_t capacity = 10)" << endl;

        _array = (DataType*)malloc(capacity * sizeof(DataType));
        if (nullptr == _array)
        {
            perror("malloc申请空间失败");
            exit(-1);
        }

        _size = 0;
        _capacity = capacity;
    }

    void Push(const DataType& data)
    {
        // CheckCapacity();
        _array[_size] = data;
        _size++;
    }

    //stack类的拷贝构造深拷贝
    Stack(const Stack& st)
    {
        cout << "Stack(const Stack& st)" << endl;
        //深拷贝开额外空间,为了避免指向同一空间
        _array = (DataType*)malloc(sizeof(DataType)*st._capacity);
        if (nullptr == _array)
        {
            perror("malloc申请空间失败");
            exit(-1);
        }
        //进行字节拷贝
        memcpy(_array, st._array, sizeof(DataType)*st._size);
        _size = st._size;
        _capacity = st._capacity;
    }

    ~Stack()
    {
        cout << "~Stack()" << endl;

        if (_array)
        {
            free(_array);
            _array = nullptr;
            _capacity = 0;
            _size = 0;
        }
    }

private:
    DataType *_array;
    size_t    _size;
    size_t    _capacity;
};

class MyQueue
{
public:
    //MyQueue什么都不写,会调用默认的构造函数,也就是Stack类的构造函数
    // 默认生成构造
    // 默认生成析构
    // 默认生成拷贝构造

private:
    //默认构造函数初始化 - 默认析构函数
    Stack _pushST;
    //默认构造函数初始化 - 默认析构函数
    Stack _popST;
    int _size = 0;
};

int main()
{
    Date d1(2023, 2, 5);
    d1.Print();

    Date d2(d1);
    Date d3 = d1; //  拷贝构造
    d2.Print();

    Stack st1;
    st1.Push(1);
    st1.Push(2);
    st1.Push(4);

    Stack st2(st1);
    cout << "=============================" << endl;

    MyQueue q1;
    //q1拷贝q2  q1中有两个Stack类和一个size,size直接拷贝,stack类是调用stack拷贝构造进行拷贝
    MyQueue q2(q1);

    return 0;
}

 

 

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

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

相关文章

为Win12做准备?微软Win11 23H2将集成AI助手:GPT4免费用

微软日前确认今年4季度推出Win11 23H2&#xff0c;这是Win11第二个年度更新。 Win11 23H2具体有哪些功能升级&#xff0c;现在还不好说&#xff0c;但它会集成微软的Copilot&#xff0c;它很容易让人想到多年前的“曲别针”助手&#xff0c;但这次是AI技术加持的&#xff0c;Co…

使用Vue+CSS实现汉堡图标过渡为叉号图标,有点意思

本文给大家分享三个具有过渡效果的汉堡图标&#xff0c;当点击汉堡图标时&#xff0c;过渡为叉号图标。这种具有过渡特效的图标挺炫酷的&#xff0c;感觉一下子给网页增加一点新颖特色。早在2015年左右&#xff0c;国外挺多优秀门户网站都有使用类似的图标&#xff0c;那时不知…

Mysql之binlog日志浅析

一、binlog日志简介 Binlog是MySQL数据库中的二进制日志&#xff0c;用于记录数据库中所有修改操作&#xff0c;包括增删改等操作。binlog以二进制格式保存&#xff0c;可以通过解析binlog文件来查看数据库的操作历史记录。binlog日志可以用于数据恢复、数据备份、数据同步等场…

智慧水务和物联网智能水表在农村供水工程中的应用

摘 要&#xff1a;随着社会的进步和各项事业的飞速发展&#xff0c;人民生活水平的逐步提升&#xff0c;国家对农村饮水安全有了更高的要求&#xff0c;为了进一步提升农村供水服务的质量&#xff0c;利用现代化、信息化科学技术提升农村供水服务质量&#xff0c;提高用水管理效…

对象分割技术在图像重绘上的运用

今年早些时候&#xff0c;Meta AI 发布了他们的新开源项目: Segment Anything Model&#xff08;SAM) &#xff0c;在计算机视觉社区引起了巨大的轰动。SAM 是一种快速分割系统&#xff0c;它擅长于对不熟悉的物体和图像进行零样本泛化&#xff0c;而不需要额外的训练。 在本教…

安全测试国家标准解读——函数调用安全、异常处理安全、指针安全

下面的系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解&#xff0c;该标准是2020年4月28日&#xff0c;由国家市场监督管理总局、国家标准化管理委员会发布&#xff0c;2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理&…

DCDC下垂控制算法

在并联的DC/DC转换器系统中&#xff0c;下垂控制&#xff08;Droop Control&#xff09;是一种常见的方法&#xff0c;用以实现在不同模块之间的功率均衡。在下垂控制策略中&#xff0c;每一个转换器的输出电压会随着负载的增加而减小&#xff0c;这样能够保证所有的转换器都在…

CSS font-family 等宽字体

CSS font-family 等宽字体 font-family: "Lucida Console", Consolas, "Courier New", Courier, monospace; font-family: Courier New, Courier, Lucida Console, Consolas, monospace; font-family: Courier, Lucida Console, Consolas, Courier New,…

【数学建模】2023 深圳杯 东三省 数学建模 B题 :电子资源版权保护问题 (基于DCT的暗水印信息嵌入模型)

在文章末尾的公众号回复&#xff1a;深圳杯B题&#xff0c;获取完整内容。 本文的文本、公式、代码都是部分展示。 文章目录 一、题目二、思路 与 解答2.1 问题一2.11 LSB 方法测试2.12 LSB 方法建模 2.2 问题二2.3 问题三2.31 方法与步骤概述2.32 基于DCT的暗水印信息嵌入模型…

第八章 HL7 架构和可用工具 - 测试转换

文章目录 第八章 HL7 架构和可用工具 - 测试转换显示段地址显示字段地址批量消息 测试转换 第八章 HL7 架构和可用工具 - 测试转换 显示段地址 要显示段地址&#xff0c;请将光标悬停在阴影列中的段名称上。工具提示显示以下内容&#xff1a; 在虚拟属性路径中使用的段地址该…

CSS样式中颜色与颜色值的应用

使用CSS描绘页面样式时&#xff0c;颜色是其中不可或缺的&#xff0c;无论是对文本、背景还是边框、阴影&#xff0c;我们都写过无数代码用来增添颜色。而为了让网页的色彩表现更出色&#xff0c;我们很有必要完整梳理下CSS中的色彩。 要讲清楚CSS中的颜色&#xff0c;离不开颜…

windows下tomcat无故宕机,检测http或https服务,并自动重启Tomcat服务

一、问题描述及解决原理 把项目发布到windows服务器中&#xff0c;如tomcat工程不稳定&#xff0c;会有无故宕机的问题。如果通过程序无法解决&#xff0c;并且重启tomcat服务能够生效的话&#xff0c;可以做一个自动检测并重启的脚本。 脚本通过检测tomcat对应的工程链接&…

flink1.17.0 jdk11服务的可以启动,web端无法访问

在配置文件中增加如下配置&#xff1a; 当前linux的ip地址&#xff0c;[localhsot&#xff0c;0.0.0.0]无效 rest.bind-address: 192.168.1.21

机器学习十大经典算法

机器学习算法是计算机科学和人工智能领域的关键组成部分&#xff0c;它们用于从数据中学习模式并作出预测或做出决策。本文将为大家介绍十大经典机器学习算法&#xff0c;其中包括了线性回归、逻辑回归、支持向量机、朴素贝叶斯、决策树等算法&#xff0c;每种算法都在特定的领…

使用 Docker Compose 部署单机版 Redis:简单高效的数据缓存与存储

家人们啦&#xff01;今天我们来介绍如何使用 docker-compose 部署单机版 Redis&#xff0c;这是一个简单高效的数据缓存与存储解决方案&#xff0c;广泛应用于Web应用、移动应用以及各类数据处理场景。我们过后几篇文章了将会介绍cluster和sentinel集群的部署。通过本文的指导…

使用css和js给按钮添加微交互的几种方式

使用css和js给按钮添加微交互的几种方式 在现实世界中&#xff0c;当我们轻弹或按下某些东西时&#xff0c;它们会发出咔嗒声&#xff0c;例如电灯开关。有些东西会亮起或发出蜂鸣声&#xff0c;这些响应都是“微交互”&#xff0c;让我们知道我们何时成功完成了某件事。在本文…

切片[::-1]解析列表list表示的“非负整数加1”

列表数位表示非负整数&#xff0c;熟练操作“满十进位”。 (本笔记适合熟练操作Python列表list的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅…

一文搞定Java NIO,以及ZipInputStream、ByteArrayInputStream各种奇葩流

目录 一、Channel1、FileChannel代码示例2、DatagramChannel代码示例3、SocketChannel 和 ServerSocketChannel代码示例 二、Buffer1、ByteBuffer示例代码2、CharBuffer示例代码3、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer 等示例代码 三、Selector1、S…

MTK system_server 卡死导致手机重启案例分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、MTK AEE Log分析工具二、AEE Log分析流程三、system_server 卡死案例分析及解决 本文主要针对 Exception Type: system_server_watchdog , system_…

激光雷达供不应求?产能过剩、毛利下滑、定点兑付风险凸显

激光雷达&#xff0c;已经供不应求&#xff1f; 以小鹏最新上市的G6车型为例&#xff0c;目前该车的Max版本在官网下订的交付时间为12周&#xff0c;原因之一就是激光雷达等核心零部件交付吃紧。 截图来自网络&#xff08;晚点Auto公众号&#xff09; 那么事实是否如此&#xf…