阿秀C++笔记-学习记录
81.C++中的组合和继承相比的优缺点
在C中组合一对象系用描述对象包对象系组一个拥对象例其变合类的含的现。这的量类当有员被创建。
以下一个示例,展示了在C++中如何实现组合关系:
class Engine {// Engine class definition...
};class Car {Engine engine;// Other member variables and functions...
};int main() {Car car;// Access car's engine through the member variable:car.engine.start(); // Example method callreturn 0;
}
在上面的示例中,Car
类中的 engine
成员变量是一个 Engine
类的对象。通过组合,Car
类中的每个对象都拥有一个引擎对象作为其一部分。在主函数中,我们可以通过 car.engine
来访问 Car
对象的引擎,并调用相关方法。
需要注意的是,组合关系不同于继承关系。在组合中,对象之间的关系是 “has-a”,而在继承中,对象之间的关系是 “is-a”。组合关系更多地体现了对象之间的整体与部分的关系。
组合也就是设计类的时候把要组合的类的对象加入到该类中作为自己的成员变量。
组合的优点:
①:当前对象只能通过所包含的那个对象去调用其方法,所以所包含的对象的内部细节对当前对象时不可见的。
②:当前对象与包含的对象是一个低耦合关系,如果修改包含对象的类中代码不需要修改当前对象类的代码。
③:当前对象可以在运行时动态的绑定所包含的对象。可以通过set方法给所包含对象赋值。
组合的缺点:①:容易产生过多的对象。②:为了能组合多个对象,必须仔细对接口进行定义。
继承
继承是Is a 的关系,比如说Student继承Person,则说明Student is a Person。继承的优点是子类可以重写父类的方法来方便地实现对父类的扩展。
继承的缺点有以下几点:
①:父类的内部细节对子类是可见的。
②:子类从父类继承的方法在编译时就确定下来了,所以无法在运行期间改变从父类继承的方法的行为。
③:如果对父类的方法做了修改的话(比如增加了一个参数),则子类的方法必须做出相应的修改。所以说子类与父类是一种高耦合,违背了面向对象思想。
85.函数调用过程栈的变化,返回值和参数变量哪个先入栈?
1、调用者函数把被调函数所需要的参数按照与被调函数的形参顺序相反的顺序压入栈中,即:从右向左依次把被调函数所需要的参数压入栈;
2、调用者函数使用call指令调用被调函数,并把call指令的下一条指令的地址当成返回地址压入栈中(这个压栈操作隐含在call指令中);
3、在被调函数中,被调函数会先保存调用者函数的栈底地址(push ebp),然后再保存调用者函数的栈顶地址,即:当前被调函数的栈底地址(mov ebp,esp);
4、在被调函数中,从ebp的位置处开始存放被调函数中的局部变量和临时变量,并且这些变量的地址按照定义时的顺序依次减小,即:这些变量的地址是按照栈的延伸方向排列的,先定义的变量先入栈,后定义的变量后入栈;
对于大部分的编程语言和操作系统,被调用函数通常会在进入函数之前保存调用者函数的栈底地址(也称为帧指针,Frame Pointer)和栈顶地址。
下面是一般的函数调用过程:
-
当一个函数被调用时,调用者函数的指令执行流会被跳转到被调用函数的入口点。
-
在被调用函数中,首先会将调用者函数的栈底地址保存到栈中,这个操作一般由
push ebp
指令完成。 -
接下来,将当前栈顶地址(esp)保存到ebp寄存器中,以成为新的栈底地址。这个过程使用
mov ebp, esp
指令完成。 -
这样,被调用函数就保存了调用者函数的栈底地址,并且在ebp寄存器中保存了新的栈底地址,可以使用ebp来访问函数参数和局部变量。
-
函数执行完成后,会使用
pop ebp
指令将保存的栈底地址还原为调用者函数的栈底地址,以返回到调用者函数。
这种操作可以建立一个新的函数执行帧,使得被调用函数能够正确地访问参数和局部变量,并在函数执行完毕后能够正确返回到调用者函数的执行位置。
需要注意的是,上述过程是一种常见的方式,但并非所有编程语言和操作系统都采用相同的方式来管理函数调用的栈帧。具体的实现可能会有所不同。
在典型的函数调用过程中,被调函数通常会使用栈来存放局部变量和临时变量。栈的延伸方向可以是向下或向上,取决于特定的体系结构和操作系统约定。在大多数情况下,栈的延伸方向是向下的,也就是地址依次减小。
对于采用向下延伸的栈,函数中的局部变量和临时变量会从ebp指针处往下分配内存空间,并按照变量定义的顺序依次排列。具体步骤如下:
-
将ebp的值保存到临时寄存器,通常使用mov指令将ebp的值存储到esp或者eax等寄存器。
-
将esp的值赋给ebp,将ebp的值设置为当前的栈顶地址,即将ebp指向当前函数的栈帧底部。
-
为该函数的局部变量和临时变量分配内存空间。根据变量的类型和大小,在ebp的位置逐渐减小的方向上分配适当的内存空间。
-
变量根据定义的顺序依次被分配在栈上,先定义的变量会在栈中较低的位置。
-
在函数的执行过程中,可以通过使用ebp加上偏移量来访问局部变量和临时变量。
需要注意的是,这种栈帧的实现方式是一种常见的做法,但并非所有的编程语言和操作系统都采用相同的方式。具体的实现可能会根据编程语言、编译器或操作系统的不同而有所变化。
91、你知道重载运算符吗?
1、 我们只能重载已有的运算符,而无权发明新的运算符;对于一个重载的运算符,其优先级和结合律与内置类型一致才可以;不能改变运算符操作数个数;
2、 两种重载方式:成员运算符和非成员运算符,成员运算符比非成员运算符少一个参数;下标运算符、箭头运算符必须是成员运算符;
3、 引入运算符重载,是为了实现类的多态性;
4、 当重载的运算符是成员函数时,this绑定到左侧运算符对象。成员运算符函数的参数数量比运算符对象的数量少一个;至少含有一个类类型的参数;
5、 从参数的个数推断到底定义的是哪种运算符,当运算符既是一元运算符又是二元运算符(+,-,*,&);
6、 下标运算符必须是成员函数,下标运算符通常以所访问元素的引用作为返回值,同时最好定义下标运算符的常量版本和非常量版本;
7、 箭头运算符必须是类的成员,解引用通常也是类的成员;重载的箭头运算符必须返回类的指针;
对第2条的解释
C++ 中的运算符重载可以使用两种方式:成员运算符重载和非成员运算符重载。它们在语法上存在一些差异,其中成员运算符重载比非成员运算符重载少一个参数。
- 成员运算符重载:使用类的成员函数作为运算符重载函数,通过成员函数来定义运算符的行为。在成员运算符重载中,运算符重载函数将被重载的运算符作为成员函数的一部分,因此成员运算符重载函数只需一个参数。
例如,可以通过重载类的成员函数 operator+()
来实现两个对象的相加运算:
class MyClass {
public:int value;MyClass() : value(0) {}MyClass operator+(const MyClass& other) {MyClass result;result.value = this->value + other.value;return result;}
};MyClass obj1;
obj1.value = 10;
MyClass obj2;
obj2.value = 20;
MyClass sum = obj1 + obj2; // 使用成员运算符重载
- 非成员运算符重载:使用独立于类的函数实现运算符重载。在非成员运算符重载中,重载函数不是类的成员函数,在函数参数中需要显式传递操作数。因此,非成员运算符重载函数需要两个参数(一个或两个操作数)。
例如,在上面的示例中,可以使用非成员函数来实现相加运算符的重载:
class MyClass {
public:int value;MyClass() : value(0) {}
};MyClass operator+(const MyClass& obj1, const MyClass& obj2) {MyClass result;result.value = obj1.value + obj2.value;return result;
}MyClass myObj1;
myObj1.value = 10;
MyClass myObj2;
myObj2.value = 20;
MyClass sum = myObj1 + myObj2; // 使用非成员运算符重载
注意,在实现非成员运算符重载时,我们没有使用成员函数,而是使用了一个独立的函数,并将对象作为参数进行操作。
无论是成员运算符重载还是非成员运算符重载,都可以实现对运算符的自定义行为,但使用成员运算符重载时,函数只接收一个操作数,而使用非成员运算符重载时,函数需要显式传递操作数。选择哪种方式主要取决于设计需求和语义上的差异。
131、介绍一下几种典型的锁
读写锁
多个读者可以同时进行读
写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
互斥锁
一次只能一个线程拥有互斥锁,其他线程只有等待
互斥锁是在抢锁失败的情况下主动放弃CPU进入睡眠状态直到锁的状态改变时再唤醒,而操作系统负责线程调度,为了实现锁的状态发生改变时唤醒阻塞的线程或者进程,需要把锁交给操作系统管理,所以互斥锁在加锁操作时涉及上下文的切换。互斥锁实际的效率还是可以让人接受的,加锁的时间大概100ns左右,而实际上互斥锁的一种可能的实现是先自旋一段时间,当自旋的时间超过阀值之后再将线程投入睡眠中,因此在并发运算中使用互斥锁(每次占用锁的时间很短)的效果可能不亚于使用自旋锁
条件变量
互斥锁一个明显的缺点是他只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,他常和互斥锁一起使用,以免出现竞态条件。当条件不满足时,线程往往解开相应的互斥锁并阻塞线程然后等待条件发生变化。一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。总的来说互斥锁是线程间互斥的机制,条件变量则是同步机制。
自旋锁
如果进线程无法取得锁,进线程不会立刻放弃CPU时间片,而是一直循环尝试获取锁,直到获取为止。如果别的线程长时期占有锁那么自旋就是在浪费CPU做无用功,但是自旋锁一般应用于加锁时间很短的场景,这个时候效率比较高。
条件变量(Condition Variable)常与互斥锁(Mutex)一起使用,以避免竞态条件(Race Condition)的发生。
竞态条件是指多个线程并发执行时,由于执行顺序不确定而导致结果的正确性受到影响的情况。当多个线程访问共享资源时,如果没有适当的同步机制,就可能引发竞态条件。
互斥锁用于保护共享资源的访问,它可以确保在任意时刻只有一个线程能够访问被保护的资源,从而避免竞态条件的发生。
但有些情况下,仅使用互斥锁可能不足以满足程序的需求。例如,当一个线程等待某个条件达成后再继续执行,就需要使用条件变量。
条件变量允许线程在满足特定条件之前阻塞,并等待其他线程发出的信号。它通常与互斥锁一起使用,以确保线程的等待和唤醒操作在互斥的情况下进行。
在使用条件变量时,通常会遵循以下模式:
-
线程获取互斥锁。
-
检查条件是否满足,如果不满足,则进入等待状态,释放互斥锁。
-
其他线程改变条件并发出信号。
-
等待的线程被唤醒后,重新获取互斥锁,并检查条件是否满足。
-
如果条件仍未满足,则回到步骤2继续等待。
使用条件变量可以确保线程在等待特定条件时被正确地阻塞,并在条件满足时被正确地唤醒。这样,互斥锁和条件变量的组合可以有效地避免竞态条件的出现。
内存泄漏和内存溢出的场景
下面列举了五种常见的 C++ 内存泄漏和内存溢出的场景:
- 忘记释放动态分配的内存:当使用
new
操作符动态分配内存后,如果忘记使用delete
操作符释放内存,就会导致内存泄漏。例如:
int* ptr = new int;
// 忘记释放内存,导致内存泄漏
- 循环引用:当存在两个或多个对象相互引用时,且这些对象使用动态分配的内存,若没有正确地释放这些对象,会导致内存泄漏。例如:
class A {
public:B* b;
};class B {
public:A* a;
};A* obj1 = new A;
B* obj2 = new B;
obj1->b = obj2;
obj2->a = obj1;
// 忘记释放 obj1 和 obj2,导致内存泄漏
- 被遗漏的析构函数:当类中定义了资源管理的逻辑(如打开文件、分配内存等),但没有正确实现析构函数来释放这些资源,会导致内存泄漏。例如:
class Resource {
public:Resource() {// 打开文件或分配内存等资源的初始化操作}// 没有实现析构函数来释放资源
};Resource* res = new Resource;
// res 对象没有被正确地释放,导致资源未被释放
- 指针迭代器使用错误:当使用指针迭代器(如 STL 容器的迭代器)时,若指针没有正确地增加或减少,可能导致指针访问越界,造成内存溢出。例如:
std::vector<int> vec{1, 2, 3, 4, 5};
auto it = vec.begin();
++it;
++it;
// 忘记检查迭代器是否越界,并导致访问了无效的内存
- 递归深度太大:在使用递归函数时,如果递归深度过大,可能导致栈溢出。每次函数调用会将函数的局部变量、返回地址等信息保存在栈上,当递归层级过多时,栈空间可能会被耗尽。例如:
void recursiveFunction() {// ...recursiveFunction();
}recursiveFunction();
// 递归层级过多,可能导致栈溢出
这些是可能导致 C++ 内存泄漏和内存溢出的一些常见场景,需要注意在编码中避免这些问题,并及时释放动态分配的内存和资源。使用智能指针、RAII 等技术可以帮助更好地管理内存。
C++内存分配
在C++中,内存分成5个区,他们分别是堆、栈、全局/静态存储区和常量存储区和代码区。
- 栈,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
- 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
- 全局/静态存储区,内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据(局部static变量,全局static变量)、全局变量和常量。
- 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量字符串,不允许修改。
- 代码区,存放程序的二进制代码
63.重载实现编译时多态,虚函数实现运行时多态
多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单一句话:允许将子类类型的指针赋值给父类类型的指针
实现多态有二种方式:覆盖(override),重载(overload)。
覆盖:是指子类重新定义父类的虚函数的做法。
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。例如:基类是一个抽象对象——人,那教师、运动员也是人,而使用这个抽象对象既可以表示教师、也可以表示运动员。
重载实现编译时多态和虚函数实现运行时多态是面向对象编程中常用的两种多态性实现方式。
- 重载实现编译时多态:
重载是指在同一个作用域内,根据不同的参数类型或参数个数定义多个同名函数。编译器在编译时根据函数调用的参数类型来确定调用哪个重载函数,这称为编译时多态。编译时多态可以根据不同参数类型的函数来执行不同的操作,提供了灵活的编程方式。
例如:
void process(int value) {// 处理整型参数的函数
}void process(float value) {// 处理浮点型参数的函数
}int main() {int a = 10;float b = 2.5f;process(a); // 调用处理整型参数的函数process(b); // 调用处理浮点型参数的函数return 0;
}
- 虚函数实现运行时多态:
虚函数是在基类中声明为虚函数,并由其派生类重写的函数。通过基类指针或引用调用虚函数时,根据对象实际的动态类型来确定调用哪个重写的函数,这称为运行时多态。运行时多态在运行时根据对象的实际类型,动态地选择调用哪个函数,提供了灵活的面向对象编程方式。
例如:
class Shape {
public:virtual void draw() {cout << "绘制形状" << endl;}
};class Circle : public Shape {
public:void draw() override {cout << "绘制圆形" << endl;}
};class Rectangle : public Shape {
public:void draw() override {cout << "绘制矩形" << endl;}
};int main() {Shape* shape1 = new Circle();Shape* shape2 = new Rectangle();shape1->draw(); // 调用Circle类的draw函数shape2->draw(); // 调用Rectangle类的draw函数delete shape1;delete shape2;return 0;
}
在上述例子中,通过定义基类Shape和派生类Circle和Rectangle,并将派生类重写基类中的虚函数draw。然后通过指向基类的指针shape1和shape2,在运行时根据实际类型调用相应的draw函数,实现了运行时多态性。
64. 成员初始化列表的概念,为什么用它会快一些
成员初始化列表是在类的构造函数中使用初始化列表来初始化类成员变量的一种方式。
使用成员初始化列表可以带来一些性能上的优势,主要有以下几点:
-
避免了多余的默认构造和析构过程:在构造函数中,如果类成员变量是通过赋值来初始化的,会先调用默认构造函数创建一个临时对象,然后再调用赋值操作符将临时对象的值赋给成员变量。而使用初始化列表,可以直接在对象创建的过程中将初值传递给成员变量,避免了多余的构造和析构操作,提高了效率。
-
对于 const 成员变量和引用类型成员变量,只能通过初始化列表来初始化:const 成员变量在对象创建后就不能被修改,引用类型成员变量必须在创建时绑定到一个对象。使用初始化列表可以直接在对象创建时提供初值,确保 const 成员变量和引用类型成员变量的正确初始化。
-
一些复杂的成员对象可能没有默认构造函数或者为其提供默认参数是不可行的:有些类需要非默认的构造函数来接收参数或者执行特定的初始化过程。如果通过赋值操作符来初始化这些成员对象,可能会遇到没有默认构造函数的问题。使用初始化列表可以在构造函数中直接调用相应的构造函数来初始化这些复杂的成员对象。
总的来说,成员初始化列表可以提高初始化的效率,避免多余的操作,并且对于 const 成员变量和引用类型成员变量是必须的。它是一种推荐的初始化方式,特别是在构造函数中有复杂的初始化需求或者对性能要求较高的情况下。
65.C++的四种强制转换reinterpret_cast/const_cast/static_cast /dynamic_cast
C++中的四种强制转换(static_cast、dynamic_cast、const_cast和reinterpret_cast)有以下区别:
-
static_cast:主要用于基本类型之间的转换、继承层次结构中的上行转换(派生类指针转为基类指针)、void指针和其他指针类型之间的转换等。在编译时完成类型检查,具有一定的安全性。
-
dynamic_cast:主要用于继承层次结构中的下行转换(将基类指针或引用转换为派生类指针或引用)。运行时进行类型检查,如果转换失败会返回空指针(对指针)或抛出std::bad_cast异常(对引用)。
-
const_cast:主要用于去除指针或引用的const或volatile属性,实现指针或引用的类型转换,用于修改类型的常量性属性。但要注意,const_cast只能用于改变指针或引用的底层const性质,不能用于改变被指对象的常量性。
-
reinterpret_cast:主要用于指针之间的强制类型转换,它会将一个指针类型转换为完全不同的指针类型,即便是不同类型之间的转换,都可以使用reinterpret_cast。它主要用于特殊的场景,如指针和整数之间的转换,或者不同种类指针之间的转换,但使用时需要谨慎,因为它执行的是低级操作,可能会导致未定义行为。
需要注意的是,任何类型之间的强制转换都可能带来潜在的风险,因此在使用强制转换时需要谨慎,并确保转换的安全性和正确性。
delete和delete[]的区别
delete
和delete[]
是在C++中用于释放动态分配的内存的操作符,它们有一些区别:
-
delete
用于释放使用new
操作符分配的单个对象的内存。例如:MyClass* obj = new MyClass; delete obj;
。它会调用对象的析构函数,并释放对应的内存。 -
delete[]
用于释放使用new[]
操作符分配的数组对象的内存。例如:int* arr = new int[5]; delete[] arr;
。它会调用数组中每个元素的析构函数(如果有的话),然后释放整个数组所占的内存空间。
需要注意的是,使用delete
释放使用new[]
分配的数组对象的内存(或使用delete[]
释放使用new
分配的单个对象的内存)是不正确的,这种行为会导致未定义的行为,可能会造成内存泄漏或程序崩溃。
因此,当你使用new
分配单个对象时,请使用delete
释放内存;当你使用new[]
分配数组对象时,请使用delete[]
释放内存。这样可以确保正确释放内存并避免潜在的问题。
相关文章:

阿秀C++笔记-学习记录
81.C中的组合和继承相比的优缺点 在C中组合一对象系用描述对象包对象系组一个拥对象例其变合类的含的现。这的量类当有员被创建。 以下一个示例,展示了在C中如何实现组合关系: class Engine {// Engine class definition... };class Car {Engine engi…...

前端入门到入土?
文章目录 前言http和https的区别,https加密的原理是?区别https的加密原理 TCP为什么要三次握手?proxy代理的原理?内存泄漏?什么是内存泄漏?为什么会有内存泄漏?内存泄漏的情况?如何防…...

架构设计基础设施保障IaaS之网络
目录 1 DNS运用1.1 DNS功能作用1.2 DNS配置实践 2 DNS生产最佳实践方案2.1 全球加速功能2.2 不同运营商的加速方案2.3 全球业务高可用方案2.4 跨地域负载均衡 3 DNS域名劫持解决方案4 CDN剖析4.1 CDN原理4.2 缓存过期配置处理流程4.3 缓存配置规则 5 CDN运用6 CDN最佳实践方案6…...

zabbix安装部署
前期准备:安装mysql数据库和nginx 一、下载zabbix rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/7/x86_64/zabbix-release-4.4-1.el7.noarch.rpm yum-config-manager --enable rhel-7-server-optional-rpms yum install epel-release numactl yum install…...

零碎的C++
构造函数和析构函数 构造函数不能是虚函数,而析构函数可以是虚函数。原因如下: 构造函数不能是虚函数,因为在执行构造函数时,对象还没有完全创建,还没有分配内存空间,也没有初始化虚函数表指针。如果构造…...

模糊测试面面观 | 模糊测试是如何发现异常情况的?
协议模糊测试是一种用于评估通信协议、文件格式和API实现系统安全性和稳定性的关键技术。在模糊测试过程中,监视器扮演着关键角色,它们能够捕获异常情况、错误响应、资源利用等,为测试人员提供有价值的信息,有助于发现潜在漏洞和问…...

C#备份数据库文件
c#备份数据库文件完整代码 sqlServer 存储过程: USE [PSIDBase] GO /****** Object: StoredProcedure [dbo].[sp_BackupDB] Script Date: 2023/8/31 16:49:02 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GOALTER procedure [dbo].[sp_BackupDB]…...

行军遇到各种复杂地形怎么处理?
行军遇到各种复杂地形怎么处理? 【安志强趣讲《孙子兵法》第30讲】 【原文】 凡军好高而恶下,贵阳而贱阴,养生而处实,军无百疾,是谓必胜。 【注释】 阳,太阳能照到的地方。阴,太阳照不到的地方。…...

Python Number(数字).............................................
Python Number 数据类型用于存储数值。 数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间。 以下实例在变量赋值时 Number 对象将被创建: var1 1 var2 10您也可以使用del语句删除一些 Number 对象引用。 del语句…...

设置 Hue Server 与 Hue Web 界面之间的会话超时时间
设置 Hue Server 与 Hue Web 界面之间的会话超时时间 在 CDH 的 Hue 中,Auto Logout Timeout 参数表示用户在不活动一段时间后将自动注销(登出)的超时时间。当用户在 Hue 中处于不活动状态超过该设定时间时,系统将自动注销用户&am…...

openGauss学习笔记-57 openGauss 高级特性-并行查询
文章目录 openGauss学习笔记-57 openGauss 高级特性-并行查询57.1 适用场景与限制57.2 资源对SMP性能的影响57.3 其他因素对SMP性能的影响57.4 配置步骤 openGauss学习笔记-57 openGauss 高级特性-并行查询 openGauss的SMP并行技术是一种利用计算机多核CPU架构来实现多线程并行…...

软考(1)-面向对象的概念
目录 一. 软考基本信息 1. 软考时间: 2. 软考科目: 3.专业知识介绍 -- 综合知识考点分布 4. 专业介绍 -- 软件设计考点分布 二. 面向对象概念 1. 封装 考点一:对象 考点二:封装private 2. 继承 考点三:类 考…...

深度学习推荐系统(四)WideDeep模型及其在Criteo数据集上的应用
深度学习推荐系统(四)Wide&Deep模型及其在Criteo数据集上的应用 在2016年, 随着微软的Deep Crossing, 谷歌的Wide&Deep以及FNN、PNN等一大批优秀的深度学习模型被提出, 推荐系统全面进入了深度学习时代, 时至今日&#x…...

第十二章 YOLO的部署实战篇(中篇)
cuda教程目录 第一章 指针篇 第二章 CUDA原理篇 第三章 CUDA编译器环境配置篇 第四章 kernel函数基础篇 第五章 kernel索引(index)篇 第六章 kenel矩阵计算实战篇 第七章 kenel实战强化篇 第八章 CUDA内存应用与性能优化篇 第九章 CUDA原子(atomic)实战篇 第十章 CUDA流(strea…...

面试题查漏补缺 i++和 ++ i哪个效率更高
i 和 i 哪个效率更高? 在这里声明,简单地比较前缀自增运算符和后缀自增运算符的效率是片面的,因为存在很多因素影响这个问题的答案。首先考虑内建数据类型的情况:如果自增运算表达式的结果没有被使用,而是仅仅简单地用于增加一员…...

Docker的数据管理(持久化存储)
文章目录 一、概述二、数据卷三、数据卷容器四、端口映射五、容器互联(使用centos镜像)总结 一、概述 管理 Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器(DataVolumes Containers&a…...

定时脚本自动自动将文件push到git
写脚本 绝对路径 环境注意 写python,bash脚本执行调用 py程序 定制crontab -e 日志要指定输入文件中 项目地址 https://gitee.com/stdev_1/sshpi10/ bash脚本 #!/bin/bash 设置要监控的仓库路径 #path~/github/ #watch_dir“/home/pi/gittest/ipset/sshpi10” p…...

025: vue父子组件中传递方法控制:$emit,$refs,$parent,$children
第025个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…...

使用js搭建简易的WebRTC实现视频直播
首先需要一个信令服务器,我们使用nodejs来搭建。两个端:发送端和接收端。我的目录结构如下图:流程 创建一个文件夹 WebRTC-Test。进入文件夹中,新建一个node的文件夹。使用终端并进入node的目录下,使用 npm init 创建p…...

LeetCode 2707. Extra Characters in a String【动态规划,记忆化搜索,Trie】1735
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...

设计模式行为型-模板模式
文章目录 一:模板方法设计模式概述1.1 简介1.2 定义和目的1.3 关键特点1.4 适用场景 二:模板方法设计模式基本原理2.1 抽象类2.1.1 定义和作用2.1.2 模板方法2.1.3 具体方法 2.2 具体类2.2.1 定义和作用2.2.2 实现抽象类中的抽象方法2.2.3 覆盖钩子方法 …...

9.3.tensorRT高级(4)封装系列-自动驾驶案例项目self-driving-车道线检测
目录 前言1. 车道线检测总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。 本次课程学习 tensorRT 高级-自动驾驶案例项目self-driving-车道…...

django.core.exceptions.AppRegistryNotReady: Apps aren‘t loaded yet.
运行django测试用例报错django.core.exceptions.AppRegistryNotReady: Apps arent loaded yet. 解决:在测试文件上方加上 django.setup() django.setup()是Django框架中的一个函数。它用于在非Django环境下使用Django的各种功能、模型和设置。 在常规的Django应用…...

【C#】C#调用进程打开一个exe程序
文章目录 一、过程二、效果总结 一、过程 新建WinForm程序,并写入代码,明确要调用的程序的绝对路径(或相对路径)下的exe文件。 调用代码: 这里我调用的另一个程序的路径是: F:\WindowsFormsApplication2…...

宝塔面板定时监控和重启MySQL数据库(计划任务)
往期教程 如果还有不了解宝塔面板怎么使用的小伙伴,可以看下我总结的系列教程,保证从新手变老鸟: 【建站流程科普】 个人和企业搭建网站基本流程及六个主要步骤常见的VPS主机运维面板汇总—网站运维面板云服务器,VPS࿰…...

Beats:安装及配置 Metricbeat (二)- 8.x
这篇文章是继文章 “Beats:安装及配置 Metricbeat (一)- 8.x” 的续篇。你可以先阅读之前的那篇文章再继续阅读这篇文章。我们在这篇文章中继续之前的探讨。 使用 fingerprint 来代替证书 在实际的使用中,我们需要从 Elasticsear…...

Redis之哨兵模式解读
目录 基本介绍 单哨兵模式 多哨兵模式 哨兵的本质 配置哨兵模式 故障恢复原理 哨兵监控工作流程 哨兵模式缺点 基本介绍 当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多…...

题目:2644.找出可整除性得分最大的整数
题目来源: leetcode题目,网址:2644. 找出可整除性得分最大的整数 - 力扣(LeetCode) 解题思路: 遍历计算即可。 解题代码: class Solution {public int maxDivScore(int[] nums, int[] di…...

报错:axios 发送的接口请求 404
axios 发送的接口请求 404 一、问题二、分析 一、问题 二、分析 axios 发送的接口请求 404,根本没有把接口信息发送到后端,这个时候你可以查看检查一下自己的接口名字,或让后端配合换一个接口名字再发送一次接口请求...

三年前端还不会配置Nginx?刷完这篇就够了
什么是Nginx Nginx是一个开源的高性能HTTP和反向代理服务器。它可以用于处理静态资源、负载均衡、反向代理和缓存等任务。Nginx被广泛用于构建高可用性、高性能的Web应用程序和网站。它具有低内存消耗、高并发能力和良好的稳定性,因此在互联网领域非常受欢迎。 为…...