cpp_07_类型转换构造_析构函数_深拷贝_静态成员

news2024/11/16 7:42:27

1  类型转换构造函数

1.1  why?

        基本类型之间的转换,编译器内置转换规则:int -> double

        类类型之间的转换,编译器不知道转换规则,需要用户提供:Cat -> Dog

// consconv_why.cpp 为什么需要自定义转换
#include <iostream>
using namespace std;

class Cat {
public:
    Cat( const char* name ) : m_name(name) {
        //【string m_name(name);】
    }
    void talk( ) {
        cout << m_name << ": 喵喵~~~" << endl;
    }
private:
    string m_name;
};

class Dog {
public:
    Dog( const char* name ) : m_name(name) {
        //【string m_name(name);】
    }
    void talk( ) {
        cout << m_name << ": 汪汪~~~" << endl;
    }
private:
    string m_name;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    Cat smallwhite("小白");
    smallwhite.talk( );

    Dog bigyellow = smallwhite; // Cat --> Dog

    return 0;
}

1.2  理论

        class   目标类型 {

                   目标类型 ( const  源类型&  src ) { ... }  // 类型转换构造函数

                    };

        用于:

        1)利用一个已定义的对象,来定义另一个不同类型的对象

        2)实现从源类型到目标类型的隐式类型转换 

        通过explicit关键字,可以强制  这种通过类型转换构造函数实现的类型转换  必须通过静态转换显示地进行:

        class  目标类型 {

                explicit  目标类型 ( const  源类型&  src ) { ... };

        };

// consconv.cpp
// 类型转换构造函数 -- 指定 源类型 到 目标类型 的 转换规则
#include <iostream>
using namespace std;

class Cat {
public:
    explicit Cat( const char* name ) : m_name(name) { // 类型转换构造函数
        //【string m_name(name);】
        cout << "Cat类的类型转换构造函数被调用" << endl;
    }
    void talk( ) {
        cout << m_name << ": 喵喵~~~" << endl;
    }
private:
    string m_name;
    friend class Dog; // 友元声明
};

class Dog {
public:
    Dog( const char* name ) : m_name(name) { // 类型转换构造函数
        //【string m_name(name);】
    }
    explicit Dog( const Cat& c ) : m_name(c.m_name) { // 类型转换构造函数(Cat-->Dog的转换规则)
        //【string m_name=c.m_name;】
        cout << "Dog类的类型转换构造函数被调用" << endl;
    }
    void talk( ) {
        cout << m_name << ": 汪汪~~~" << endl;
    }
private:
    string m_name;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
//  Cat smallwhite("小白"); // 定义smallwhite,利用smallwhite.Cat("小白")->类型转换构造函数

//  Cat smallwhite = "小白"; // 定义 匿名Cat类对象,利用 匿名Cat类对象.Cat("小白")->隐式转换
                             // Cat smallwhite=匿名Cat类对象-->克隆
   
    Cat smallwhite = static_cast<Cat>("小白"); 
                             // 定义 匿名Cat类对象,利用 匿名Cat类对象.Cat("小白")->静态转换
                             // Cat smallwhite=匿名Cat类对象-->克隆
    smallwhite.talk( );

//    Dog bigyellow(smallwhite); // 定义bigyellow,利用bigyellow.Dog(smallwhite)->类型转换构造函数

//    Dog bigyellow = smallwhite; // 定义 匿名Dog类对象,利用 匿名Dog类对象.Dog(smallwhite)->隐式类型转换
                                // Dog bigyellow = 匿名Dog类对象-->克隆
    Dog bigyellow = static_cast<Dog>(smallwhite); 
                                    // 定义 匿名Dog类对象,利用 匿名Dog类对象.Dog(smallwhite)->静态类型转换
                                    // Dog bigyellow = 匿名Dog类对象-->克隆
    bigyellow.talk( );
    return 0;
}

2  析构函数

2.1  理论

        析构函数的函数名就是在类名前面加“~”,没有返回类型没有参数,不能重载。

        在销毁对象之前一刻自动被调用,且仅被调用一次 :

                - 对象离开作用域

                - delete操作符

        作用:销毁  对象的各个成员变量 

        如果一个类没有定义析构函数,那么编译器会为其提供一个默认的析构函数:

                - 对基本类型的成员变量,什么也不做。

                - 对类类型的成员变量,调用相应类型的析构函数。

                - 销毁 对象的各个成员变量 

2.2  析构过程

        

        对象的销毁过程:

        1)调用析构函数

                - 执行自己在析构函数中书写的代码 

                - 利用类成员变量调用相应的析构函数 

                - 释放对象的各成员变量所占内存空间 

        2)释放整个对象所占用的内存空间 

// 析构函数
#include <iostream>
using namespace std;

class Human {
public:
//  如果类没有提供任何构造函数,编译器将提供一个无参的构造函数
/*  Human() {
       【int m_age;】定义m_age,初值为随机数
       【string m_name;】定义m_name,利用m_name.string()
    }*/
    Human( int age=0, const char* name="无名" ) : m_age(age),m_name(name) {
        //【int m_age=age;】定义m_age,初值为age
        //【string m_name(name);】定义m_name,利用m_name.string(name)
        cout << "Human类缺省构造函数被调用" << endl;
    }
//  如果类没有提供拷贝构造函数,编译器将提供一个默认的拷贝构造函数
/*  Human( const Human& that ) { 
       【int m_age=that.m_age;】定义m_age,初值为that.m_age
       【string m_name(that.m_name);】定义m_name,利用m_name.string(that.m_name)-->string类拷贝构造函数
    }*/
    Human( const Human& that ) : m_age(that.m_age), m_name(that.m_name) { 
        //【int m_age=that.m_age;】定义m_age,初值为that.m_age
        //【string m_name(that.m_name);】定义m_name,利用m_name.string(that.m_name)
        cout << "Human类拷贝构造函数被调用" << endl;
    }
//  如果类没有提供拷贝赋值函数,编译器将提供一个默认的拷贝赋值函数
/*  Human& operator=( const Human& that ) {
        this->m_age = that.m_age;
        this->m_name = that.m_name; // this->m_name.operator=(that.m_name)-->string类的拷贝赋值函数
        return *this;
    }*/
    Human& operator=( const Human& that ) {
        // 编译器不会再拷贝赋值函数中塞任何操作
        cout << "Human类的拷贝赋值函数被调用" << endl;
        this->m_age = that.m_age;
        this->m_name = that.m_name; // this->m_name.operator=(that.m_name)-->string类的拷贝赋值函数
        return *this;
    }
//  如果类没有提供析构函数,编译器将提供一个默认的析构函数
/*  ~Human() {
        对于基本类型成员变量m_age,什么都不做
        对于类类型成员变量m_name,利用 m_name.~string()
        释放 m_age/m_name 本身所占内存空间
    }*/
    
    ~Human() {
        cout << "Human类的析构函数被调用" << endl;
        // 对于基本类型成员变量m_age,什么都不做
        // 对于类类型成员变量m_name,利用 m_name.~string()
        // 释放 m_age/m_name 本身所占内存空间
    }
    void getinfo( ) {
        cout << "姓名: " << m_name << ", 年龄: " << m_age << endl;
    }
private:
    int m_age; // 基本类型的成员变量
    string m_name; // 类类型的成员变量
};

// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    Human h; // 定义h,利用h.Human()-->h维护的内容为(无名,0)
    h.getinfo( );

    Human h2(22,"张飞"); // 定义h2,利用h2.Human(22,"张飞")-->h2维护的内容为(张飞,22)
    h2.getinfo();

    Human h3(h2); // = h2; // 定义h3,利用h3.Human(h2)-->触发拷贝构造函数
    h3.getinfo();

    Human h4; // 定义h4,利用h4.Human()-->h4维护的内容为(无名,0)
    cout << "h4被赋值前---";
    h4.getinfo();

    h4 = h3; // h4.operator=(h3)-->触发拷贝赋值函数
    cout << "h4被赋值后---";
    h4.getinfo();
    cout << "------------main will be over----------------" << endl;
    return 0;
} //(1) h.~Human() h2.~Human() h3.~Human() h4.~Human() (2)释放h/h2/h3/h4本身所占的内存空间

2.3  has to

        通常情况下,若对象在其声明周期的最终时刻,并不持有任何动态分配的资源,可以不定义析构函数。

        若对象在其声明周期的最终时刻,持有动态资源,则必须定义析构函数,释放对象所持有的动态资源。

// hastodes必须自己写析构函数的情况 -- 对象临死时,持有动态资源
#include <iostream>
using namespace std;

class A {
public:
    A(int i) : m_i(i), m_p(new int), m_f(open("./file", O_CREAT|O_RDWR,0644)) {
        //【int m_i=i;】定义m_i,初值为i
        //【int* m_p=new int;】定义m_p,初值为指向一块堆内存(动态资源)
        //【int m_f=open(...);】定义m_f,初值为文件描述符-->文件表等内核结构(动态资源)
    }
    ~A() {
        delete m_p;
        close( m_f ); // 动态资源需要自己写代码释放

        // 释放m_i / m_p / m_f 本身所占内存空间
    }
    /* 默认析构函数
    ~A() {
        释放m_i / m_p / m_f 本身所占内存空间
    }
    */
private:
    int m_i;
    int* m_p;
    int m_f;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    A a; // 定义a,利用a.A()
    return 0;
} // a.~A()  释放a本身所占内存空间

        析构函数的功能并不局限在释放资源上,它还可以执行  我们希望在  对象被释放之前  执行的任何操作。 

3  深拷贝

3.1  浅拷贝缺陷

        如果类不提供拷贝构造,编译器将提供默认的拷贝构造。

        无论是  拷贝构造  还是  拷贝赋值,其默认实现,对任何类型的指针成员都是简单地复制地址,而并不复制地址指向的数据,这种情况称为浅拷贝。(左图)

        为了获得完整意义上的对象副本,必须自己定义  拷贝构造  和  拷贝赋值,针对指针型成员变量做深拷贝。(右图)

           

// copybytes_pre.cpp 类中有指针成员,默认拷贝构造 会有浅拷贝缺陷
#include <iostream>
#include <cstring>
using namespace std;
// 模拟C++标准的string类 实现自己的String类
class String {
public:
    String( const char* psz="" ) : m_psz(new char[strlen(psz)+1]) {
        //【char* m_psz=new char[strlen(psz)+1];】// 动态资源
        strcpy( m_psz, psz );
    }
    ~String( /* String* this */ ) {
        delete[] this->m_psz;
        // 释放 m_psz 本身所占内存空间
    }
    char* c_str() { return m_psz; }
//  默认的拷贝构造
/*  String( const String& that ) {
        【char* m_psz = that.m_psz;】只复制了地址,没有复制地址指向的数据-->浅拷贝
    }*/ 
private:
    char* m_psz;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    String s1("hello");
    cout << "s1:" << s1.c_str() << ", s1中的m_psz指向的堆内存的地址: " << (void*)s1.c_str() << endl;

    String s2(s1); // = s1; 定义s2,利用s2.String(s1)-->拷贝构造函数
    cout << "s2:" << s2.c_str() << ", s2中的m_psz指向的堆内存的地址: " << (void*)s2.c_str() << endl;
    return 0;
} // s1.~String()  s2.~String() 

        相对于拷贝构造,拷贝赋值需要做更多的工作:

                - 避免自赋值

                - 分配新资源

                - 拷贝新内容

                - 释放旧资源

                - 返回自引用

// copybytes.cpp 类中有指针成员,默认拷贝构造 会有浅拷贝缺陷
#include <iostream>
#include <cstring>
using namespace std;
// 模拟C++标准的string类 实现自己的String类
class String {
public:
    String( const char* psz="" ) : m_psz(new char[strlen(psz)+1]) {
        //【char* m_psz=new char[strlen(psz)+1];】// 动态资源
        strcpy( m_psz, psz );
    }
    ~String( /* String* this */ ) {
        delete[] this->m_psz;
        // 释放 m_psz 本身所占内存空间
    }
    char* c_str() { return m_psz; }
//  默认的拷贝构造
/*  String( const String& that ) {
        【char* m_psz = that.m_psz;】只复制了地址,没有复制地址指向的数据-->浅拷贝
    }*/
    // 深拷贝构造函数
    String( const String& that ) : m_psz(new char[strlen(that.m_psz)+1]) {
        //【char* m_psz = new char[strlen(that.m_psz)+1];】
        strcpy( m_psz, that.m_psz ); // 不复制地址,复制地址指向的数据-->深拷贝
    }
    /* 默认拷贝赋值函数
    String& operator=( const String& that ) {
        this->m_psz = that.m_psz; // 只复制了地址,没有复制地址指向的数据-->浅拷贝
        return *this;
    }
    */
    // 深拷贝赋值函数
    String& operator=( const String& that ) {
        if( this != &that ) { // 防止自赋值
            delete[] this->m_psz; // 释放旧资源
            this->m_psz = new char[strlen(that.m_psz)+1]; // 分配新资源
            strcpy( this->m_psz, that.m_psz ); // 拷贝新内容
        }
        return *this; // 返回自引用
    }
private:
    char* m_psz;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    String s1("hello");
    cout << "s1:" << s1.c_str() << ", s1中的m_psz指向的堆内存的地址: " << (void*)s1.c_str() << endl;

    String s2(s1); // = s1; 定义s2,利用s2.String(s1)-->拷贝构造函数
    cout << "s2:" << s2.c_str() << ", s2中的m_psz指向的堆内存的地址: " << (void*)s2.c_str() << endl;

    String s3; // 定义s3,利用s3.String()-->s3维护一个字节堆内存('\0')
    s3 = s2; // s3.operator=(s2)
    cout << "s3:" << s3.c_str() << ", s3中的m_psz指向的堆内存的地址: " << (void*)s3.c_str() << endl;

    return 0;
} // s1.~String()  s2.~String() 

3.2  建议

        1)只有类中有指针型成员变量,才会涉及深浅拷贝的问题,因此应尽量避免使用指针型成员变量。

        2)如果确实无法实现完整意义上的  深拷贝拷贝构造  和  深拷贝拷贝赋值,可将它们私有化,禁止用户使用。

4  静态成员

4.1  静态成员变量

        静态成员变量  不属于对象  而  属于类

                - 静态成员变量不包含在对象中,进程级生命期

                - 静态成员变量的定义和初始化,只能在  类的外部  而不能在构造函数中进行。

                - 静态成员变量依然受  类作用域  和  访问控制限定符  的约束。

                - 访问静态成员变量,既可以通过  类  也可以通过  对象。

                - 静态成员变量为该类的所有对象实例所共享

// static.cpp 类的静态成员变量
#include <iostream>
using namespace std;

// 普通成员变量:属于对象,对象的生命期      静态成员变量:不属于对象,进程级生命期
class A {
public:
    A() {
        //【int m_i;】
    }
    int m_i; // 声明
    static int m_si; // 声明
};
int A::m_si = 0; // 全局域中定义-->进程级生命期
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    A a, b; // 静态成员变量没有保存在对象内部-->不属于对象
    cout << "a对象的大小:" << sizeof(a) << endl; // 4
    cout << "b对象的大小:" << sizeof(b) << endl; // 4

    A::m_si = 888; // 静态成员受到类作用域的约束 也受到访问控制限定符的约束-->属于类

    a.m_si = 999; // A::m_si=999;
    cout << "b.m_si=" << b.m_si << endl; // A::m_si
    // 类的静态成员变量,被该类的所有对象共享
    return 0;
}

4.2  静态成员函数

        静态成员函数  不属于对象  而  属于类

                - 静态成员函数没有this指针,也没有常属性  

                - 静态成员函数依然受  类作用域  和  访问控制限定符的约束

                - 访问静态成员函数,既可以通过  类  也可以通过  对象。

                -静态成员函数只能访问静态成员,而非静态成员函数可以访问所有成员。

// static.cpp 类的 静态成员变量 和 静态成员函数
#include <iostream>
using namespace std;

// 普通成员函数:必须利用对象来调用      静态成员函数:不是必须利用对象来调用
class A {
public:
    int m_i; // 普通成员变量
    void foo( /* const A* this */ ) const { // 普通成员函数
        cout << "foo is invoked" << endl;
        cout << m_i << endl; // ok
        cout << m_si << endl;// ok
        bar();               // ok
//      以上三行代码证明 非静态成员函数 即可访问非静态成员 也可访问 静态成员(不挑食)
    }

    static int m_si; //静态成员变量
    static void bar( /*无this指针*/ ) /*const*/ { // 静态成员函数
        cout << "bar is invoked" << endl;
        cout << m_si << endl; // ok
//      cout << m_i << endl;  // error
//      foo();                // error
//      以上三行代码证明 静态成员函数 只能访问 静态成员,不能访问非静态的普通成员(挑食)
    }
};
int A::m_si = 0; // 全局域中定义-->进程级生命期
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    A a, b;
    a.foo(); // foo(&a);
    b.foo(); // foo(&b);

    A::bar(); // 受到类作用域的约束 也受到访问控制限定符的约束-->属于类
    a.bar(); // A::bar();
    b.bar(); // A::bar();
    return 0;
}

4.3  总结

                                                

        事实上,类的静态成员变量和静态成员函数,更像是普通的全局变量和全局函数,

        只是多了一层类作用域和访问控制限定符的约束,

        相当于  具有成员访问属性的全局变量和全局函数。

5  类  扩充

        空类对象的大小是1个字节。

        类中不能包含  本类对象  作为  普通成员变量;

        类中可以包含  本类对象  作为  静态成员变量。

// class_add
#include <iostream>
using namespace std;
/*
class A { // 空类
};
int main( void ) {
    A a; // 空类对象占1个字节内存(1个字节的垃圾数据)
    A& ra = a;
    cout << "空类对象a的大小: " << sizeof(a) << endl;
    return 0;
}
*/


class A {
public:
    int m_i;
//  A m_a; // error
    static A m_sa; // ok
};
int main( void ) {
    A a; // 定义a(给a分配内存空间)
    cout << "对象a的大小: " << sizeof(a) << endl;
    return 0;
}

6  单例模式

        要求:设计一个类,要求用户在使用这个类时仅有一个实例(只能出现一个对象):

        class  Singleton {

                // 设计这个类

        };

        int  main(void) {

                // 用户这里只能出现一个Singleton类对象,不能出现第二个

                return  0;

        }

        

        实现方法:

        1)将  包括类的拷贝构造函数在内的所有构造函数 私有化,防止user在类的外部创建对象。

        2)唯一的对象由类的设计者来创建

        3)提供公有静态成员函数getInstance()使用户可以获取到唯一对象。

        单例分类:

        1)饿汉式:无论用不用,程序启动即创建  hungry.cpp

        2)懒汉式:用的时候创建,不用了即销毁  lazy.cpp

// hungry_singleton.cpp
// 单例模式--要求设计一个类型,用户在使用这个类时只能出现一个对象
#include <iostream>
using namespace std;
// 恶汉式单例
class Singleton {
public://4        //5
    static Singleton& getInstance( ) {
        return s_instance;
    }
private:
    Singleton( ) {} // 1
    Singleton( const Singleton& that ) {} // 6
    static Singleton s_instance; // 2 唯一对象
};

Singleton Singleton::s_instance; // 3

// 以上代码模拟类的设计者
// -----------------------
// 以下代码模拟类的使用者
int main( void ) {
    Singleton& s1 = Singleton::getInstance( );
    Singleton& s2 = Singleton::getInstance( );
    Singleton& s3 = Singleton::getInstance( );
    cout << "&s1: " << &s1 << ", &s2: " << &s2 << ", &s3: " << &s3 << endl;
    return 0;
}

// lazy_singleton.cpp
// 单例模式:设计一个类,保证用户在使用这个类时,只能出现一个对象
#include <iostream>
using namespace std;
// 懒汉式单例:单例高级实现手法
class Singleton {
public:
    static Singleton& getInstance( ) {
        if( s_instance==NULL ) {
            s_instance = new Singleton; // 唯一的对象
            cout << "创建了唯一的对象" << endl;
        }
        ++s_counter;
        return *s_instance;
    }
    void releaseInstance( ) {
        if( --s_counter == 0 ) {
            delete s_instance;
            s_instance = NULL;
            cout << "销毁了唯一的对象" << endl;
        }
    }
private:
    Singleton() {} 
    Singleton( const Singleton& that ) {} 
    static Singleton* s_instance; // 并不是唯一对象,仅仅是一个指针而已
    static int s_counter; // 计数功能
};

Singleton* Singleton::s_instance = NULL; // 程序刚刚时,唯一的对象不存在 
int Singleton::s_counter = 0;

// 以上的代码模拟类的设计者(例如:类库、被人设计的类、自己的设计的类)
// -------------------------------------
// 以下的代码模拟用户(使用类的人)
int main( void ) {
    Singleton& s1 = Singleton::getInstance(); // 第一次调用getInstance函数时,创建唯一的对象
    Singleton& s2 = Singleton::getInstance(); // 以后再调用getInstance函数时,返回第一次调用时创建的对象
    Singleton& s3 = Singleton::getInstance(); // ...
    cout << "&s1: " << &s1 << ", &s2: " << &s2 << ", &s3: " << &s3 << endl;
    s1.releaseInstance( ); //
    s2.releaseInstance( ); // 
    s3.releaseInstance( ); // 最后一次调用releaseInstance才将对象销毁
    return 0;
}

​​​​​​​

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

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

相关文章

多出口-热备---实验

多出口-热备 拓扑 需求 1&#xff09;增加出口路由器&#xff0c;实现路由器冗余&#xff0c;实现出口设备热备份 配置步骤 1&#xff09;SW5和SW6创建vlan25 vlan26 2) SW5配置vlanif 25的IP地址 3&#xff09;S 4&#xff09;统一规划设计一下MSTP 5&#xff09;R2配…

Java中利用Redis,ZooKeeper,数据库等实现分布式锁(遥遥领先)

1. 分布式锁 1.1 什么是分布式锁 在我们进行单机应用开发涉及并发同步的时候&#xff0c;我们往往采用synchronized或者ReentrantLock的方式来解决多线程间的代码同步问题。但是当我们的应用是在分布式集群工作的情况下&#xff0c;那么就需要一种更加高级的锁机制&#xff0…

奇富科技跻身国际AI学术顶级会议ICASSP 2024,AI智能感知能力迈入新纪元

近日&#xff0c;2024年IEEE声学、语音与信号处理国际会议ICASSP 2024&#xff08;2024 IEEE International Conference on Acoustics, Speech, and Signal Processing&#xff09;宣布录用奇富科技关于语音情感计算的最新研究成果论文“MS-SENet: Enhancing Speech Emotion Re…

java设计模式学习之【状态模式】

文章目录 引言状态模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用状态示例代码地址 引言 设想你正在使用一个在线视频播放器观看电影。随着你的互动&#xff0c;播放器可能处于不同的状态&#xff1a;播放、暂停、缓冲或结束。每个状态下&#xff0c;播放…

IDEA安装教程及使用

一、IDEA简介 ​ IDEA全称IntelliJ IDEA&#xff0c;是用于Java语言开发的集成环境&#xff0c;它是业界公认的目前用于Java程序开发最好的工具。 集成环境&#xff1a;把代码编写&#xff0c;编译&#xff0c;执行&#xff0c;调试等多种功能综合到一起的开发工具。 二、ID…

数据分析之词云图绘制

试验任务概述&#xff1a;如下为所给CSDN博客信息表&#xff0c;分别汇总了ai, algo, big-data, blockchain, hardware, math, miniprog等7个标签的博客。对CSDN不同领域标签类别的博客内容进行词频统计&#xff0c;绘制词频统计图&#xff0c;并根据词频统计的结果绘制词云图。…

使用streampark进行flink on k8s LoadBalancer配置域名访问flink ui

在使用yarn部署flink任务时&#xff0c;yarn自动代理了flink web ui&#xff0c;通过yarn的地址即可访问任务web页面。 k8s模式下想访问flink web ui&#xff0c;要么使用NodePort的方式启动任务&#xff0c;然后通过k8s主机IPNodePort端口来进行访问。但是这种方法&#xff0…

C++构建简单静态库实例(cmakelist)

一、开发实例 通过cmake构建静态开发实例如下: 1.1 代码目录 代码目录结构如下: 1.2 代码内容 1.2.1 CMakeLists.txt # CMake 最低版本要求 cmake_minimum_required(VERSION 3.10)# 项目名称 project(mylib)# 添加源文件 set(SOURCE_FILESsrc/mylib

分布式数据库 GaiaDB-X 通过 GB18030-2022《信息技术 中文编码字符集》最高级别认证

近日&#xff0c;百度智能云分布式数据库GaiaDB-X通过 GB18030-2022《信息技术 中文编码字符集》强制性国家标准测试&#xff0c;达到最高实现级别&#xff08;3级&#xff09;。 据了解&#xff0c;GB18030-2022《信息技术 中文编码字符集》是中文信息技术领域最重要的基础性标…

在 Unity 中获取 Object 对象的编辑器对象

有这个需求的原因是&#xff0c;在编辑器的 Inspector 逻辑中&#xff0c;写了许多生成逻辑。 现在不想挨个在 Inspector 上都点一遍按钮&#xff0c;所以就需要能获取到它们的编辑器对象。 发现可以借助官方的 UnityEditor.Editor.CreateEditor 方法达到目的&#xff0c;如下…

【IoT网络层】STM32 + ESP8266 +MQTT + 阿里云物联网平台 |开源,附资料|

目标&#xff1a;实现STM32连接阿里云物联网平台发送数据同时接收数据&#xff0c;IOT studio界面显示数据。具体来说&#xff1a;使用ESP8266 ESP-01来连接网络&#xff0c;获取设备数据发送到阿里云物联网平台并显示且oled显示屏当前的设备数据&#xff0c;通过IOT studio界面…

OpenHarmony城市技术论坛武汉站:探索大模型时代的终端操作系统创新

2023年12月23日下午,OpenHarmony城市技术论坛(以下简称“技术论坛”)——第6期(武汉站)于华中科技大学梧桐语问学中心明德报告厅圆满举办。本次技术论坛聚焦“大模型时代的系统软件”,旨在探索AI大模型在终端操作系统领域的创新趋势和挑战。论坛从“终端操作系统十大技术挑战”…

亿赛通电子文档安全管理系统 linkfilterservice 未授权漏洞

产品简介 亿赛通电子文档安全管理系统&#xff0c;&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资…

php 之 redisk 扩展问题

系统&#xff1a; ARM V10 server &#xff08;1229&#xff09; 软件&#xff1a; php、phpdevel redis5.1.0RC1 redis5.1.0RC1.tgz phpredis 编译&#xff1a; 解压进入目录内&#xff1a; # phpize # ./configure withphpconfig/usr/bin/phpconfig # make # make ins…

【1】Docker详解与部署微服务实战

Docker 详解 Docker 简介 Docker 是一个开源的容器化平台&#xff0c;可以帮助开发者将应用程序和其依赖的环境打包成一个可移植、可部署的容器。Docker 的主要目标是通过容器化技术实现应用程序的快速部署、可移植性和可扩展性&#xff0c;从而简化应用程序的开发、测试和部…

机器学习——决策树(三)

【说明】文章内容来自《机器学习——基于sklearn》&#xff0c;用于学习记录。若有争议联系删除。 1、案例一 决策树用于是否赖床问题。 采用决策树进行分类&#xff0c;要经过数据采集、特征向量化、模型训练和决策树可视化4个步骤。 赖床数据链接&#xff1a;https://pan…

SLAM算法与工程实践——相机篇:RealSense D435使用(2)

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

基于ChatGpt,Java,SpringBoot,Vue,Milvus向量数据库的定制化聊天Web demo

customized chat GitHub - bigcyy/customized-chatgpt: 基于ChatGpt&#xff0c;Java&#xff0c;SpringBoot&#xff0c;Vue&#xff0c;Milvus向量数据库的定制化聊天Web demo 简介 基于ChatGpt&#xff0c;Java&#xff0c;SpringBoot&#xff0c;Vue&#xff0c;Milvus向…

基于SpringBoot+thymeleaf+layui 宠物医院预约管理系统(Java毕业设计有文档)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

1 - 数据库服务概述 | 构建MySQL服务 | 数据库基本管理 | MySQL基本类型

数据库服务概述 | 构建MySQL服务 | 数据库基本管理 | MySQL基本类型 数据库服务概述构建mysql服务安装mysql软件包连接mysql服务器 修改密码 密码管理修改密码策略&#xff08;需要登陆&#xff09;破解数据库管理员root密码&#xff08;数据库服务处于运行状态但是root忘记了密…