C++知识点:类和对象(自用)

news2024/12/23 6:57:47

类和对象

  • 1. 类和对象的关系
  • 2. 对象指针
  • 3. 在堆上创建对象
  • 4. 成员访问限定符
  • 5. 名字编码(Name Mangling)
  • 6.构造函数
  • 7.构造函数的重载
  • 8.初始化列表
  • 8. 成员变量初始化的顺序(通过初始化列表)
  • 9. 初始化 const 成员变量
  • 10. 析构函数
  • 11. 析构函数的执行时机!!
  • 12. 对象数组及其初始化
  • 12. 成员对象和封闭类
  • 13. 成员对象的初始化和析构顺序
  • 14. this 指针
  • 15. static静态成员变量
  • 16. static静态成员函数和普通成员函数的区别
  • 17. const成员变量和const成员函数
  • 18. const在函数的位置区别。
  • 18. const对象(常对象)
  • 19. 友元函数和友元类(friend关键字)
  • 20. string类
  • 21. 附录总结


引用:
[1]C语言中文网


1. 类和对象的关系

类是一种复杂数据类型的声明,并不占用内存空间。对象是类实例化后的具体实例,是类这个数据类型的一个变量,占用内存空间

类的定义(声明)不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。

类名的首字母一般大写

类定义的最后有一个分号";",它是类定义的一部分,表示类定义结束了,不能省略。

除了创建单个对象,还可以创建对象数组:

class Student {
      int age;
      char *name;
};

Student liyi; //创建单个对象
Student class_51[100]; //创建对象数组
liyi.age = 18; //创建对象以后才会给成员变量分配内存
liyi.name = 'liyi';

2. 对象指针

可以创建对象指针指向实例化后的对象。具体方法如下:

Student liyi; //创建单个对象
Student *pstu = &liyi;

3. 在堆上创建对象

知识点前提:栈区是程序自动管理的,不需要人为的释放内存。堆区是程序员自己管理的,必须自行释放内存。即,new和delete必须成对出现。

Student liyi; //在栈区实例化对象
Student *pstu = new Student; //在堆区实例化对象

我们在栈区创建的对象是有名字,即liyi。我们可以通过liyi这个对象名直接访问到对应的数据。所以,一般没必要用对象指针指向它。但是new操作符所创建的对象在堆区,返回的是一个指针,没有名字(简单来说就是,new创建的对象是匿名的)。如果没有对应的对象指针进行接收,则该对象无法访问了。

对象指针后,可以通过箭头->来访问对象的成员变量和成员函数。

通过对象名字访问成员使用点号.,通过对象指针访问成员使用箭头->。

4. 成员访问限定符

public: 类内可以访问,类外可以访问。
private:类内可以访问,类外不可以通过对象访问。
protected:类内可以访问,类外不可以通过对象访问,但是在它的派生类内部可以访问。

如果既不写 private 也不写 public,就默认为 private。

5. 名字编码(Name Mangling)

前提知识:C++对于对象进行分配内存时,只分配成员变量的内存。
不同对象的成员函数代码相同,所以不同对象分别分配自己的成员变量,同时共享成员函数代码。截图来自C语言中文网。在这里插入图片描述

那么如何确定每个对象自己的成员函数代码呢。这就需要借助C++编译器的名字编码。C++在每次编译的时候,会根据所属类名,命名空间,参数列表等不同对成员函数名进行重新编码。

在这里插入图片描述

6.构造函数

  • 构造函数会在创建对象时自动调用,不需要用户显式调用(用户也不能调用)。如果用户没有创建,则编译器会自动创建构造函数。一旦用户自己定义了构造函数,编译器则不会自动生成。
  • 构造函数必须是public属性,其他属性虽然不会报错,但是创建的构造函数没有意义。
  • 构造函数没有返回值,所以函数声明前不能有任何数据类型,并且函数体中不能有 return 语句。
  • 构造函数在实际开发中往往用来做一些初始化工作

7.构造函数的重载

构造函数是必须调用的,在创建对象的时候,必定会执行一个构造函数。如果构造函数重载,则必须有一组参数列表和其中一个构造函数相匹配。

8.初始化列表

class Student{
private:
	char* m_name;
	int m_age;
public:
	// 初始化列表方法:
	Student(char* name, int age):m_name(name), m_age(age){}
	//等价于Student(char* name, int age){ m_name = name; m_age=age;}
}

使用构造函数初始化列表并没有效率上的优势,仅仅是书写方便。

8. 成员变量初始化的顺序(通过初始化列表)

成员变量的初始化顺序与初始化列表中列出的变量的顺序无关,它只与成员变量在类中声明的顺序有关。

class Student{
private:
	int m_age;
	int m_age2;
public:
	Student(int age):m_age2(age), m_age(m_age2){}
	//错误理解:Student(int age){ m_age2= age; m_age=m_age2;}
	//正确理解:Student(int age){ m_age= m_age2; m_age2=age;}
}

在这里插入图片描述顺序修改后:
在这里插入图片描述
所以,尽量按照成员变量的声明的顺序进行初始化。

9. 初始化 const 成员变量

初始化 const 成员变量的唯一方法就是使用初始化列表。

错误方法:
在这里插入图片描述

10. 析构函数

  • 析构函数会在销毁对象时自动调用,不需要用户显式调用(用户也不能调用)。如果用户没有创建,则编译器会自动创建构造函数。析构函数是唯一的,不能重载!!!
  • 析构函数必须是public属性,其他属性虽然不会报错,但是创建的析构函数没有意义。
  • 析构函数没有返回值,所以函数声明前不能有任何数据类型,并且函数体中不能有 return 语句。
  • 析构函数在实际开发中往往用来做一些销毁内存(new,malloc创建的堆区变量,关闭文件)

示例:
在这里插入图片描述

11. 析构函数的执行时机!!

  • 在函数外创建的对象,是全局对象,类似于全局变量。数据存储在全局数据区,当全局作用域结束后,程序自动销毁存储在全局数据区的对象,调用其析构函数。
  • 在函数中创建的对象,是局部对象,类似于局部变量。数据存储在栈区,当函数结束后,程序自动销毁存储在栈区的对象,调用其析构函数。
  • 通过new创建的对象,也是局部对象,但是其存储在堆区,由程序员自动管理如果没有delete操作,则程序结束也不会调用其析构函数。所以,new申请的对象内存,一定要delete进行删除。
  • 析构遵循,先构造的后析构原则。

举例如下:
在这里插入图片描述

12. 对象数组及其初始化

对象数组的初始化,如果只有一个参数,可以隐式调用。如果由多个参数则应该显式调用

举例:

class Student{
private:
    char* m_name;
    int m_age;
public:
	// 没有参数
    Student():m_name("Null"),m_age(0){
        cout<<" construct m_name is "<< m_name << ", m_age is "<<m_age<<endl;
    }
    // 只有一个参数
    Student(char* name):m_name(name),m_age(0){
        cout<<" construct m_name is "<< m_name << ", m_age is "<<m_age<<endl;
    }
    // 两个参数(可类比多个)
    Student(char* name, int age):m_name(name), m_age(age){
        cout<<" construct m_name is "<< m_name << ", m_age is "<<m_age<<endl;
    }
    ~Student(){cout<<" destruct m_name is "<< m_name << ", m_age is "<<m_age<<endl;}
};

int main(){
	// 如果不给参数,默认调用Student()
    Student stu[2] = {}; 
    // 如果只有一个参数,则可以隐式的直接给参数,例如"only_one_params"。
    Student stu2[2] = {"only_one_params"};// 第一个是隐式调用,第二个是默认构造(也是隐式)
    // 如果只有两个参数(多个),则需要显示调用,例如Student("only_two_params", 2)。
    Student stu3[2] = {"only_one_params", Student("only_two_params", 2)}; // 第二个就是显示调用。
    return 0;
}

在这里插入图片描述
注意:
如果是对象指针数组,则必须显示调用,并且创建几个对象就是几个对象。少的那个没有初始化,其指针值是随机的。

举例:

    Student* stu4[3] = {
            new Student("only_one_params"),
            new Student("only_two_params", 2),
    };

同时也可以验证之前的观点,new创建的对象,如果没有delete则不会进行析构。

12. 成员对象和封闭类

  • 当类中的成员变量是对象时,被称为成员对象。
  • 包含成员对象的类叫封闭类。

13. 成员对象的初始化和析构顺序

当封闭类创建对象时,需要先创建成员对象。对于成员对象的初始化,需要借助封闭类的构造函数初始化列表方法

特殊情况,当封闭类的构造函数没有对成员对象进行初始化时,如果成员对象有无参数的构造函数。则会通过无参数的构造函数进行初始化,如果有参数,则会报错。因此,封闭类必须对成员对象进行初始化。

成员对象的构造和析构,遵循先构造后析构的原则。即,先对成员对象进行构造,再对封闭类对象进行构造。先对封闭类对象进行析构,再对成员对象进行析构。

举例:

class Age{
private:
    int m_age;
public:
	//无参数的构造函数
    Age():m_age(0){cout<<" construct Age , m_age is "<<m_age<<endl;}
    Age(int age):m_age(age){cout<<" construct Age, m_age is "<<m_age<<endl;}
    ~Age(){cout<<" destruct Age, m_age is "<<m_age<<endl;}
};

class Name{
private:
    char* m_family_name;
    char* m_last_name;
public:
    Name(char* f_name, char* l_name):m_family_name(f_name), m_last_name(l_name){cout<<" construct is "<< m_family_name<<" " << m_last_name <<endl;}
    ~Name(){cout<<" destruct is "<< m_family_name<<" " << m_last_name <<endl;}
};

// 封闭类
class Student{
private:
	// 成员对象
    Name m_c_name;
    Age m_c_age;
public:
    // 初始化构建Age类和Name类的成员对象。
    Student(char* f_name, char* l_name, int age):m_c_name(f_name, l_name), m_c_age(age){cout<<" construct Student is Class"<<endl;};
    // 测试是否调用Age类中无参数构造函数的成员对象
    Student(char* f_name, char* l_name):m_c_name(f_name, l_name){cout<<" construct Student is Class"<<endl;};
    ~Student(){cout<<" destruct Student is Class"<<endl;}
};

int main(){
    Student stu("li", "si", 22);
//    Student stu2("zhang", "san"); 
    return 0;
}

从结果看,可以发现先通过构造函数创建成员对象m_c_name和成员对象m_c_age(顺序是成员对象声明顺序和初始化列表顺序无关),然后再通过封闭类构造函数创建对象stu。析构时的顺序先是封闭类析构函数,再是成员类析构函数。遵循先构造后析构原则。
(成员类析构函数顺序也是先构造后析构)
在这里插入图片描述

 Student stu2("zhang", "san"); //会调用无参数的构造函数

在这里插入图片描述

14. this 指针

this指针是一个const 指针,指向当前对象,且作用域范围是在成员函数内部。调用方法为"->"

注意:

  • this 是 const 指针,它的值是不能被修改的。
  • this 只能在成员函数内部使用。
  • 只有当对象被创建后 this 才有意义,因此不能在 static 成员函数中使用。
  • this 实际上是成员函数的一个隐式形参

15. static静态成员变量

不同对象之间成员变量相互独立。但是有时想要多个对象共享一个成员变量,此时就可以通过静态成员变量来实现。静态成员变量是一种特殊的成员变量,它被关键字static修饰

静态成员变量在类内声明,属于类,不属于对象。

static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。


初始化:

  • static 成员变量必须在类声明的外部初始化
  • 静态成员变量在初始化时不能再加 static,但必须要有数据类型
  • static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。

static 成员变量和普通的 static 变量类似,都在内存分区中的全局数据区分配内存,到程序结束时才释放。

初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化为 0。全局数据区的变量都有默认的初始值 0,而动态数据区(堆区、栈区)变量的默认值是不确定的,一般认为是垃圾值。[1]

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

举例:

class Student{
private:
    char* m_name;
    int m_age;
public:
    static int m_num;
public:
    // 初始化构建Age类和Name类的成员对象。
    Student(char* name, int age):m_name(name), m_age(age){
        m_num ++;
    };
    ~Student(){}
    void show();
};

void Student::show(){
    cout << "class num is "<<m_num<<endl;
}

// 在类外对静态成员变量进行初始化。该数据存储在全局数据区,程序结束自动销毁。
int Student::m_num = 0;

int main(){
    // 通过对象调用。
    (new Student("zhangsan", 20))->show();
    (new Student("lisi", 18))->show();
    (new Student("wangwu", 22))->show();
    //直接通过类名直接调用。
    cout << "check class num by class name. the num is "<<Student::m_num<<endl;
    return 0;
}
/*
输出:
class num is 1
class num is 2
class num is 3
check class num by class name. the num is 3
*/

16. static静态成员函数和普通成员函数的区别

静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量静态成员函数)。

类似于python中的@staticmethod修饰的成员函数,其中没有self变量。

17. const成员变量和const成员函数

const成员变量只能通过初始化列表进行初始化,这点在第9点说过。

const成员函数可以访问类中所有的成员变量,但是不能修改它们的值。目的是为了保护数据。

方法是在成员函数头的尾部加上const关键字。

举例:

class Student{
private:
    char* m_name;
    int m_age;
public:
// 声明时函数头后加const关键字
     int getAge() const;
public:
    Student(char* name, int age):m_name(name), m_age(age){};
    ~Student(){}
};

// 定义时,函数头后也加const关键字
int Student::getAge() const{
    return m_age;
}

int main(){
    Student stu("zhaoliu", 25);
    int num = stu.getAge();
    cout << "check class num by class name. the num is "<<num<<endl;
    return 0;
}

const成员函数不能修改内部的成员变量。如下图:
在这里插入图片描述

18. const在函数的位置区别。

  • 函数开头的 const 用来修饰函数的返回值,表示返回值是 const 类型,也就是不能被修改,例如const char * getname()。
  • 函数头部的结尾加上 const 表示常成员函数,这种函数只能读取成员变量的值,而不能修改成员变量的值,例如char * getname() const。

18. const对象(常对象)

如果对象被const修饰,则被称为常对象。在常对象中,只能使用const成员变量和const成员函数。

19. 友元函数和友元类(friend关键字)

当外部函数想要访问一个类中的private修饰的成员变量和成员函数时,可以借助friend关键字进行修饰,如果修饰的函数,则是友元函数,如果修饰的是类,则是友元类(友元类中所有的成员函数都是友元函数。)

  • 友元函数可以类外的函数(全局函数),也可以是类内的成员函数
  • friend关键字一定在类内。其声明的函数或者类,称为友元函数和友元类,可以访问该类中的所有成员变量。
  • friend修饰的函数,一定要有对象,对象指针或者对象引用。类比于this指针,友元函数和友元类中的成员函数,都需要借助对象对该类的private成员进行访问。
  • 友元函数和友元类是单向的不是双向的,例如B是A的友元类,可以访问A中所有成员变量。但是A不是B的友元类。
  • 友元函数和友元类不可传递,例如B是A的友元类,A是C的友元类,但是B不是C的友元类。

全局函数:

class Student{
private:
    char* m_name;
    int m_age;
public:
    Student(char* name, int age):m_name(name), m_age(age){};
    ~Student(){}
    // 第二步:声明为Student类的友元函数,我们要访问Student类,就把friend定义到Student类中。
    friend void show(Student * ptu);
};

//类外的全局函数想要访问Student类中的私有成员变量。
//第一步:参数需要有对象、对象指针或者对象引用
void show(Student * ptu){
    cout<< "this student name is "<< ptu->m_name << "  , age is "<<ptu->m_age<<endl;
}

int main(){
    Student stu("zhaoliu", 25);
    // 直接调用全局函数show(),并把对象传进去。
    show(&stu);
    return 0;
}
/*
输出:
this student name is zhaoliu  , age is 25
*/

类内的成员函数:

class Student; // 提前声明,不然void show(Student * ptu);中Student未定义。

class Test{
    //类内的成员函数想要访问Student类中的私有成员变量。
    //第一步:参数需要有对象、对象指针或者对象引用
public:
    void show(Student * ptu);
};

class Student{
private:
    char* m_name;
    int m_age;
public:
    Student(char* name, int age):m_name(name), m_age(age){};
    ~Student(){}
    // 第二步:声明为Student类的友元函数,我们要访问Student类,就把friend定义到Student类中。
    friend void Test::show(Student * ptu);
};

void Test::show(Student * ptu){
    cout<< "this student name is "<< ptu->m_name << "  , age is "<<ptu->m_age<<endl;
}

int main(){

    Student stu("zhaoliu", 25);
    // 直接调用全局函数show(),并把对象传进去。
    Test test;
    test.show(&stu);
    return 0;
}
/*
输出:
this student name is zhaoliu  , age is 25
*/

友元类:

// 除了friend void Test::show(Student * ptu);改为 friend Test;
// 其他把和类内成员函数声明为友元函数一样
class Student{
private:
    char* m_name;
    int m_age;
public:
    Student(char* name, int age):m_name(name), m_age(age){};
    ~Student(){}
    // 第二步:声明为Student类的友元类,我们要访问Student类,就把friend定义到Student类中。
    friend Test;
};

void Test::show(Student * ptu){
    cout<< "this student name is "<< ptu->m_name << "  , age is "<<ptu->m_age<<endl;
}

除非有必要,一般不建议把整个类声明为友元类,而只将某些成员函数声明为友元函数,这样更安全一些。

20. string类

  • 相比C语言中的字符串,string类对象声明的字符串数据,末尾不包括’\0’。
  • string类可以直接用 “=”进行赋值。
  • string类中有length()函数,该函数直接返回字符串的长度,因为末尾没有’\0’,所以返回的也是真是字符串长度。
  • string 类可以使用+或+=运算符来直接拼接字符串,不需要使用C语言中的 strcat()、strcpy()、malloc() 等函数来拼接字符串了,也不用担心空间不够会溢出。
  • string类转化为c语言的字符串,可以通过 “.c_str()”来实现。

string类的增上改查:

  • 插入字符串:
int main(){
    string s1, s2;
    s1 = "1234567890";
    s2 = "aaa";
    s1.insert(2, s2);//第一个是字符串下表,第二个是插入的字符或字符串
    cout<< s1 <<endl;
    return 0;
}
/*
输出:12aaa34567890
*/
  • 删除字符串:
int main(){
    string s1;
    s1 = "1234567890";
    s1.erase(5);// 第二个参数如果不指定,则从第一个下标(包含)后到末尾全删除
    cout<< s1 <<endl;
    s1.erase(2, 1); // 第一个是字符串下标,第二个是要删除几个字符。
    cout<< s1 <<endl;
    return 0;
}
/*
输出:
12345
1245
*/
  • 提取子字符串
int main(){
    string s1, s2;
    s1 = "1234567890";
    s2= s1.substr(5, 2);// 第一个是字符串下标,第二个是从下标开始(包含)提取多少个字符
    cout<< s2 <<endl;
    return 0;
}
/*
输出:
67
*/
  • 字符串查找
int main(){
    string s1, s2;
    s1 = "1234567890";
    s2 = "567";
    int index= s1.find(s2, 2); // 第一个参数是需要查找的子字符串,第二个参数是从第几个字符开始查,如果不指定则从第0个字符开始查。
    cout<< index <<endl;
    return 0;
}
/*
输出:
4
*/

还有其他两个查找函数:
rfind()函数:在find函数中,第二个参数表示从该参数下标开始查,而rfind函数则是从0字符查到第二个参数的下标。如果查不到返回-1

int main(){
    string s1, s2;
    s1 = "1234567890";
    s2 = "567";
    int index= s1.find(s2, 2);
    cout<< index <<endl;
    int index2= s1.rfind(s2, 2);
    cout<< index2 <<endl;
    int index3= s1.rfind(s2, 6);
    cout<< index3 <<endl;
    return 0;
}
/*
输出:
4
-1
4
*/

find_first_of() 函数:find_first_of() 函数用于查找子字符串和字符串共同具有的字符在字符串中首次出现的位置。

int main(){
    string s1, s2;
    s1 = "123 234 345";
    s2 = "a32";
    int index= s1.find_first_of(s2);
    cout<< index <<endl;
    return 0;
}
/*
输出:
1
*/

s1和s2共有的字符有“3”和“2”,在这两个中,首次出现下标是1。

21. 附录总结

该总结引用自[1]C语言中文网,如果想学习更详细的内容,可以去该网址学习。

  • 类的成员有成员变量和成员函数两种。

  • 成员函数之间可以互相调用,成员函数内部可以访问成员变量。

  • 私有成员只能在类的成员函数内部访问。默认情况下,class 类的成员是私有的,struct 类的成员是公有的。

  • 可以用“对象名.成员名”、“引用名.成员名”、“对象指针->成员名”的方法访问对象的成员变量或调用成员函数。成员函数被调用时,可以用上述三种方法指定函数是作用在哪个对象上的。

  • 对象所占用的存储空间的大小等于各成员变量所占用的存储空间的大小之和(如果不考虑成员变量对齐问题的话)。

  • 定义类时,如果一个构造函数都不写,则编译器自动生成默认(无参)构造函数和复制构造函数。如果编写了构造函数,则编译器不自动生成默认构造函数。一个类不一定会有默认构造函数,但一定会有复制构造函数。

  • 任何生成对象的语句都要说明对象是用哪个构造函数初始化的。即便定义对象数组,也要对数组中的每个元素如何初始化进行说明。如果不说明,则编译器认为对象是用默认构造函数或参数全部可以省略的构造函数初始化。在这种情况下,如果类没有默认构造函数或参数全部可以省略的构造函数,则编译出错。

  • 对象在消亡时会调用析构函数。

  • 每个对象有各自的一份普通成员变量,但是静态成员变量只有一份,被所有对象所共享。静态成员函数不具体作用于某个对象。即便对象不存在,也可以访问类的静态成员。静态成员函数内部不能访问非静态成员变量,也不能调用非静态成员函数。

  • 常量对象上面不能执行非常量成员函数,只能执行常量成员函数。

  • 包含成员对象的类叫封闭类。任何能够生成封闭类对象的语句,都要说明对象中包含的成员对象是如何初始化的。如果不说明,则编译器认为成员对象是用默认构造函数或参数全部可以省略的构造函数初始化。

  • 在封闭类的构造函数的初始化列表中可以说明成员对象如何初始化。封闭类对象生成时,先执行成员对象的构造函数,再执行自身的构造函数;封闭类对象消亡时,先执行自身的析构函数,再执行成员对象的析构函数。

  • const 成员和引用成员必须在构造函数的初始化列表中初始化,此后值不可修改。

  • 友元分为友元函数和友元类。友元关系不能传递。

  • 成员函数中出现的 this 指针,就是指向成员函数所作用的对象的指针。因此,静态成员函数内部不能出现 this 指针。成员函数实际上的参数个数比表面上看到的多一个,多出来的参数就是 this 指针。

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

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

相关文章

【Web爬虫逆向】“企业预警通”模糊查询公司信息,逆向案例实战

“企业预警通”模糊查询公司信息&#xff0c;逆向案例实战 功能介绍效果演示思路分析1、先找到模糊查询的接口2、分析headers与params中参数并进行构造3、JS逆向&#xff0c;跟栈&#xff0c;找到js中key和dataCategory的生成方法&#xff0c;并完成js补码构造4、成功还原key后…

嵌入式中什么是三次握手

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c;点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 在网络数据传输中&#xf…

Mysql的主从复制(重要)和读写分离(理论重要实验不重要)

一、主从复制&#xff1a;架构一般是一主两从。 1.主从复制的模式&#xff1a; mysql默认模式为异步模式&#xff1a;主库在更新完事务之后会立即把结果返回给从服务器&#xff0c;并不关心从库是否接收到以及从库是否处理成功。缺点&#xff1a;网络问题没有同步、防火墙的等…

论文阅读:Deep_Generic_Dynamic_Object_Detection_Based_on_Dynamic_Grid_Maps

目录 概要 Motivation 整体框架流程 技术细节 小结 不足 论文地址&#xff1a;Deep Generic Dynamic Object Detection Based on Dynamic Grid Maps | IEEE Conference Publication | IEEE Xplore 概要 该文章提出了一种基于动态网格图&#xff08;Dynamic Grid Maps&a…

DevExpress WPF中文教程:如何完成GridControl的列和编辑器配置?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

基于微信小程序的校园警务系统/校园安全管理系统/校园出入管理系统

摘要 伴随着社会以及科学技术的发展&#xff0c;小程序已经渗透在人们的身边&#xff0c;小程序慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;小程序这一名词已不陌生&#xff0c;越来越多的学校机构等都会定制一款属于自己个性化的小程…

Exponential Moving Average (EMA) in Stable Diffusion

1.Moving Average in Stable Diffusion (SMA&EMA) 1.Moving average 2.移动平均值 3.How We Trained Stable Diffusion for Less than $50k (Part 3) Moving Average 在统计学中&#xff0c;移动平均是通过创建整个数据集中不同选择的一系列平均值来分析数据点的计算。 …

树莓集团——缔造国际领先的数字媒体产业孵化基地

在数字化浪潮席卷全球的背景下&#xff0c;树莓集团以其卓越的创新能力&#xff0c;正在全力打造一个全球领先的数字媒体产业基地。成都国际数字影像产业园不仅是技术和创意的汇聚地&#xff0c;更是数字内容创新与应用的典范&#xff0c;推动数字媒体产业迈向新的高度。 树莓集…

vue.js入门

目录 一. 框架概述 二. vue常用命令 2.1 插值表达式 2.2 v-text 2.3 v-html 2.4 v-on 2.5 v-model 2.6 v-show 2.7 v-if 2.8 v-else 2.9 v-bind 2.10 v-for 三. vue生命周期函数 一. 框架概述 我们之前写的javaScript代码都是原生的,而框架是在基础语言之上,对其进…

pytorch-梯度下降

梯度下降 y x 2 ∗ s i n ( x ) y ′ 2 x s i n x x 2 c o s x x 1 x − Δ y ′ ( x ) 其中 Δ 表示学习率&#xff0c; y ′ ( x ) 代表 y 在 x 点处关于 x 的梯度。 y x^2 * sin(x) \\ y 2xsinxx^2cosx \\ x_1 x - \Delta y(x) \\ 其中 \Delta 表示学习率&#xff0c…

qt表格模型视图

Qt 提供了一套强大的模型/视图框架&#xff0c;允许你以一种非常灵活和高效的方式显示和处理数据。在 Qt 中&#xff0c;表格视图&#xff08;TableView&#xff09;和模型&#xff08;TableModel&#xff09;是这种框架的一部分&#xff0c;常用于显示和编辑表格数据。 以下是…

便携式气象仪:科技赋能,让气象观测更智能

随着科技的快速发展&#xff0c;越来越多的领域受益于技术的进步。其中&#xff0c;气象观测领域也不例外。传统的气象观测设备虽然精确可靠&#xff0c;但往往体积庞大、携带不便&#xff0c;且需要专业人员进行操作和维护。而便携式气象仪的出现&#xff0c;则打破了这一局限…

BGP路由反射器

原理概述 缺省情况下&#xff0c;路由器从它的一个 IBGP对等体那里接收到的路由条目不会被该路由器再传递给其他IBGP对等体&#xff0c;这个原则称为BGP水平分割原则&#xff0c;该原则的根本作用是防止 AS内部的BGP路由环路。因此&#xff0c;在AS内部&#xff0c;一般需要每台…

深度解读大语言模型中的Transformer架构

一、Transformer的诞生背景 传统的循环神经网络&#xff08;RNN&#xff09;和长短期记忆网络&#xff08;LSTM&#xff09;在处理自然语言时存在诸多局限性。RNN 由于其递归的结构&#xff0c;在处理长序列时容易出现梯度消失和梯度爆炸的问题。这导致模型难以捕捉长距离的依…

《知识点扫盲 · Redis 序列化器》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【2024最新版】Stable diffusion汉化版安装教程(附SD安装包),一键激活,永久免费!

目前广泛使用的Stable Diffusion Web UI简称(SDWebUI)是发布在开源平台Github上的一个Python项目,与通常的软件安装方法不同,这个项目并不是下载并安装即可使用的应用程序,而是需要准备执行环境,编译源码. 如果你是一个新手不会安装,现在可以直接使用一键启动包. 例如:国内的…

【Linux】信号量与生产消费模型

我们已经实现过锁条件变量的PC模型&#xff0c; 但是BlockingQueue并不能进行生产与消费的并发&#xff0c;原因在于我们使用的是STL提供的队列&#xff0c;进行了一个适配&#xff0c;底层的实现可能会修改到成员变量造成未知的错误。 而这次我们选择使用环形队列&#xff08…

python实现盲反卷积算法

python实现盲反卷积算法 盲反卷积算法算法原理算法实现Python实现详细解释优缺点应用领域盲反卷积算法 盲反卷积算法是一种图像复原技术,用于在没有先验知识或仅有有限信息的情况下,估计模糊图像的原始清晰图像和点扩散函数(PSF)。盲反卷积在摄影、医学成像、天文学等领域…

监控Windows文件夹下面的文件(C#和C++实现)

最近在做虚拟打印机时&#xff0c;需要实时监控打印文件的到达&#xff0c;并移动文件到另外的位置。一开始我使用了线程&#xff0c;在线程里去检测新文件的到达。实际上Windows提供了一个文件监控接口函数ReadDIrectoryChangesW。这个函数可以对所有文件操作进行监控。 ReadD…

当 Nginx 出现请求的乱序到达,如何处理?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; 文章目录 当 Nginx 出现请求的乱序到达&#xff0c;如何处理&#xff1f;一、理解请求乱序到达的现象二、请求乱序到达可能带来的影响三、解决方案&#xff08;一&#xf…