从C语言到C++(五)
从C语言到C++(五)
- 自动类型推导
- 尾拖返回类型
- 类型信息推导
- `typeid`
- 1. 定义和基本作用
- 2. 使用方法
- 3. 注意事项
- 4. 示例代码
- 5. 关联概念:RTTI
- `decltype`
- 基本用法
- 示例
- 注意事项
- 总结
- 基于范围的增强for循环
- 示例 1:使用数组
- 示例 2:使用`std::vector`
- 示例 3:使用`std::map`
- 函数
- 1. 函数重载(Overloading)
- 调用机制
- 2. 内联函数(Inline Functions)
- 内联函数的作用
- 内联函数的限制
- 3. 引用参数(Reference Parameters)
- 4. 默认参数(Default Parameters)
- 默认参数
- 占位参数
- 5. 模板函数(Template Functions)
- 6. 成员函数(Member Functions)
自动类型推导
在C++中,自动类型推导(Automatic Type Deduction)主要通过auto
关键字实现。当你使用auto
关键字声明一个变量时,编译器会根据初始化该变量的表达式的类型来自动推断出变量的类型。
以下是一些使用auto
进行自动类型推导的例子:
#include <iostream>
#include <vector>int main() {// 基本类型推导auto a = 10; // a的类型是intauto b = 3.14f; // b的类型是float// 引用类型推导int x = 10;auto& ref_x = x; // ref_x的类型是int&,它是对x的引用// 指针类型推导int* ptr_x = &x;auto ptr_y = &x; // ptr_y的类型是int*// 复杂类型推导std::vector<int> v = {1, 2, 3, 4, 5};auto first = v.begin(); // first的类型是std::vector<int>::iterator// 初始化列表推导auto c = {1, 2, 3}; // 在C++11中,这可能会推导出std::initializer_list<int>// 但如果auto与&结合使用,则可以推导出引用到数组auto& d = {1, 2, 3}; // 错误:不能对临时对象使用引用// 但可以这样使用:int arr[] = {1, 2, 3};auto& e = arr; // e的类型是int(&)[3],即arr的引用return 0;
}
注意:
- 使用
auto
可以使代码更加简洁和清晰,但也可能导致可读性降低,特别是在复杂类型的情况下。因此,在使用auto
时,需要权衡代码的可读性和简洁性。 auto
不会推导为引用类型,除非你明确使用&
。同样,它也不会推导为指针类型,除非你明确使用*
或&
运算符。auto
不能用于函数参数或模板参数的类型推导。在这些情况下,你需要明确指定类型。- 在C++17中,引入了结构化绑定(Structured Bindings),它允许你使用
auto
来同时声明多个变量,并从元组、对、结构体等中提取值。例如:auto [x, y] = std::make_pair(1, 2);
。
尾拖返回类型
在C++中,尾置返回类型(Trailing Return Type)或称为后置返回类型(Postfix Return Type)是一种在函数声明或定义中指定返回类型的语法特性,它特别有用于处理模板函数中返回类型依赖于模板参数的情况。尾置返回类型允许你在函数声明或定义的参数列表之后指定返回类型。
尾置返回类型的使用语法通常与auto
关键字结合,并且使用->
操作符来指定返回类型。以下是一个简单的例子,展示了如何在模板函数中使用尾置返回类型:
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {return t + u;
}
在上面的例子中,decltype(t + u)
就是尾置返回类型。它告诉编译器,这个函数的返回类型是t
和u
相加的结果类型。
不过,从C++14开始,我们可以使用auto
关键字直接在函数声明中推断返回类型,而不需要显式地使用尾置返回类型:
template<typename T, typename U>
auto add(T t, U u) {return t + u;
}
编译器会根据return
语句中的表达式来推断函数的返回类型。这种自动类型推断使代码更加简洁和易读。
然而,在某些情况下,尾置返回类型仍然是必要的。例如,当返回类型依赖于多个参数,或者当返回类型是一个复杂的表达式,而不仅仅是函数参数的一个简单操作时,尾置返回类型就派上了用场。此外,它还可以用于解决某些类型推导问题,特别是当涉及引用折叠(reference collapsing)和std::forward
等高级模板技术时。
类型信息推导
typeid
typeid
是C++中的一个操作符,它用于在运行时获取一个类型或对象的实际类型信息。以下是关于typeid
的详细解释:
1. 定义和基本作用
typeid
是C++中的一个操作符,它用于获取一个类型或对象的运行时类型信息。- 在程序中,当我们需要获取某个对象或变量的类型信息时,可以使用
typeid
操作符。 typeid
的返回值是一个type_info
类型的对象,它包含了被查询对象的类型信息和一些相关函数和属性。
2. 使用方法
typeid
类似于sizeof
这样的操作符,但不是函数。typeid
定义在typeinfo
头文件中。- 可以通过
typeid(变量或类型).name()
来获取类型的名称,但需要注意的是,不是所有编译器都会输出如"int"、"float"等这样的类型名称。 typeid
可以用于动态类型,也可以用于静态类型。静态类型和动态类型分别对应的是编译时和运行时的类型识别。typeid
多数运用于class
和继承中。
3. 注意事项
- 对于非引用类型,
typeid
是在编译时期识别的;只有引用类型才会在运行时识别。 - 运行时获知变量类型名称时,可以使用
typeid(变量).name()
,但需要注意返回的类型名称可能因编译器而异。
4. 示例代码
#include <iostream>
#include <typeinfo>
using namespace std;int main(void) {int a;char b;unsigned char c;signed char d;cout << "a typeid =" << typeid(a).name() << endl; // 打印a的类型cout << "b typeid =" << typeid(b).name() << endl; // 打印b的类型cout << "c typeid =" << typeid(c).name() << endl; // 打印c的类型cout << "d typeid =" << typeid(d).name() << endl; // 打印d的类型return 0;
}
5. 关联概念:RTTI
typeid
与RTTI(Run-Time Type Identification,运行时类型识别)紧密相关。RTTI使程序能够获取由基类指针或引用所指向的对象的实际派生类型。
总结:typeid
是C++中用于在运行时获取类型信息的关键字,通过它我们可以获取一个类型或对象的实际类型信息,这在处理复杂的类型系统或进行类型检查和转换时非常有用。
decltype
decltype
是 C++11 引入的一个关键字,用于在编译时从表达式中推导类型。decltype
的主要作用是在编译时检查一个表达式并返回该表达式的类型,而不实际计算该表达式。这使得 decltype
在模板元编程、自动类型推导和函数返回类型推导等场景中特别有用。
基本用法
decltype
的基本语法如下:
decltype(expression) var;
这里 expression
是一个表达式,decltype
会根据这个表达式的类型来推导 var
的类型。
示例
- 基本类型推导
int x = 10;
decltype(x) y = 20; // y 的类型是 int
- 表达式推导
int a = 10, b = 20;
decltype(a + b) sum = a + b; // sum 的类型是 int
- 引用类型推导
int& ref = a;
decltype(ref) another_ref = b; // another_ref 是 int& 类型,它引用 b
- 函数返回类型推导
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {return t + u;
}// 或者在 C++14 及以后使用自动返回类型推导
template<typename T, typename U>
auto add(T t, U u) {return t + u;
}
在上面的例子中,decltype(t + u)
用于推导函数 add
的返回类型,它依赖于参数 t
和 u
的类型以及它们相加的结果类型。
注意事项
decltype
并不计算表达式的值,它只是检查表达式的类型。- 当
decltype
用于未声明的变量或表达式时,编译器会报错。 - 如果表达式是一个左值(如变量、数组元素、结构体的成员等),
decltype
会推导出一个引用类型。如果表达式是一个右值(如字面量、临时对象等),则推导出的类型不是引用。 - 可以通过添加括号来改变
decltype
的推导行为。例如,decltype((variable))
总是推导出一个引用类型,即使variable
是一个右值。
总结
decltype
是 C++ 中的一个强大工具,它允许程序员在编译时从表达式中推导类型,而无需显式指定。这使得代码更加灵活和易于维护,特别是在处理复杂类型和模板元编程时。
基于范围的增强for循环
在C++11及更高版本中,引入了基于范围的for
循环(Range-based for
loop),也被称为"for-each"循环,用于简化对容器(如数组、std::vector
、std::list
、std::set
等)或其他可迭代对象的遍历。
基于范围的for
循环的语法如下:
for (declaration : range) {// 循环体
}
在这里,declaration
是每次循环时从range
中提取出的元素的声明,而range
是一个可迭代的对象,比如一个容器。
下面是一些基于范围的for
循环的示例:
示例 1:使用数组
#include <iostream>int main() {int arr[] = {1, 2, 3, 4, 5};for (int num : arr) {std::cout << num << ' ';}std::cout << std::endl;return 0;
}
示例 2:使用std::vector
#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};for (int num : vec) {std::cout << num << ' ';}std::cout << std::endl;return 0;
}
示例 3:使用std::map
当遍历std::map
时,你可以同时获得键和值。
#include <iostream>
#include <map>int main() {std::map<std::string, int> myMap = {{"apple", 1}, {"banana", 2}, {"cherry", 3}};for (const auto& pair : myMap) {std::cout << pair.first << ": " << pair.second << std::endl;}return 0;
}
在这个例子中,pair
是一个std::pair<const std::string, int>
类型的对象,其中first
是键,second
是值。我们使用const auto&
来避免不必要的拷贝,并提高性能。
基于范围的for
循环在C++编程中非常有用,因为它使代码更简洁,同时仍然保持了很好的可读性。这种循环特别适合于只读迭代,当你不需要直接访问迭代器的时候。如果你需要修改迭代器(例如,在遍历过程中删除元素),那么你可能需要使用传统的迭代器循环。
函数
从C语言过渡到C++时,函数的概念在很多方面是相似的,但C++为函数提供了更多的特性和灵活性。以下是C和C++中函数的一些主要差异和C++特有的功能:
1. 函数重载(Overloading)
在C++中,函数重载(Function Overloading)是一种特性,它允许我们为同一个函数名定义多个版本,只要这些版本的参数列表(参数类型、参数数量或参数顺序)不同即可。编译器会根据调用时提供的参数类型和数量来确定调用哪个版本的函数。
下面是一个关于函数重载的例子:
#include <iostream>
#include <string>// 第一个版本的print函数,接受一个整数参数
void print(int x) {std::cout << "Printing an integer: " << x << std::endl;
}// 第二个版本的print函数,接受一个浮点数参数
void print(double x) {std::cout << "Printing a double: " << x << std::endl;
}// 第三个版本的print函数,接受一个字符串参数
void print(const std::string& s) {std::cout << "Printing a string: " << s << std::endl;
}// 第四个版本的print函数,接受两个整数参数
void print(int x, int y) {std::cout << "Printing two integers: " << x << " and " << y << std::endl;
}int main() {print(10); // 调用第一个版本的print函数print(10.5); // 调用第二个版本的print函数print("Hello"); // 调用第三个版本的print函数print(10, 20); // 调用第四个版本的print函数return 0;
}
在上面的例子中,我们定义了四个名为print
的函数,每个函数都接受不同类型的参数或不同数量的参数。在main
函数中,我们根据提供的参数类型和数量来调用不同版本的print
函数。
函数重载必须满足以下条件:
- 函数名必须相同。
- 参数列表必须不同(可以是参数类型、参数数量或参数顺序不同)。
- 返回类型不参与函数重载的判定(即返回类型不同不能构成重载)。
注意:在C++中,函数重载是通过参数列表来区分的,而不是通过函数名或返回类型。因此,你不能仅通过改变函数名或返回类型来重载一个函数。
此外,还有一个需要注意的点是,当使用默认参数时,重载函数可能会产生歧义。例如,如果你有一个接受一个整数参数的函数和一个接受两个整数参数(其中第二个参数有默认值)的函数,那么只传递一个整数参数给这两个函数时,编译器可能无法确定要调用哪个函数。因此,在设计函数重载时要避免这种情况。
调用机制
在C++中,函数重载的调用机制主要依赖于函数的名称和参数列表(即参数的类型、数量和顺序)。当编译器遇到对某个函数的调用时,它会根据提供的参数来确定应该调用哪个重载版本。这个过程称为名称查找(Name Lookup)和重载解析(Overload Resolution)。
以下是重载函数调用机制的基本步骤:
-
名称查找(Name Lookup):
- 编译器首先会在当前作用域中查找与调用名称匹配的函数声明。
- 如果在当前作用域中找不到匹配的函数声明,编译器会继续在包含当前作用域的作用域中查找,直到找到全局作用域。
- 这个过程会找到所有与调用名称匹配的函数声明,包括所有重载版本。
-
重载解析(Overload Resolution):
- 一旦编译器找到了所有与调用名称匹配的函数声明,它就会开始重载解析过程。
- 重载解析的主要任务是确定应该调用哪个重载版本的函数。这是通过比较调用时提供的参数与每个重载版本的参数列表来完成的。
- 编译器会尝试将提供的参数与每个重载版本的参数列表进行匹配。匹配的过程包括类型转换(如果需要的话),但通常编译器会优先考虑那些不需要类型转换的匹配。
- 如果某个重载版本的参数列表与提供的参数完全匹配(即不需要任何类型转换),那么这个版本就是最佳匹配,编译器将调用这个版本的函数。
- 如果没有找到完全匹配的版本,编译器会尝试找到最接近的匹配。这通常涉及到类型转换和类型提升。编译器会考虑所有可能的类型转换,并选择一个“最佳”的匹配。
- 如果存在多个同样“好”的匹配(例如,两个函数都需要相同的类型转换),编译器就会报错,因为这种情况下无法确定应该调用哪个函数。这被称为“重载解析失败”。
-
调用函数:
- 一旦确定了要调用的函数版本,编译器就会生成代码来调用该函数。这通常涉及到将参数传递给函数,并执行函数的代码。
需要注意的是,函数重载只与参数列表有关,与函数的返回类型无关。也就是说,你不能仅仅通过改变函数的返回类型来重载一个函数。此外,函数重载也与函数的定义位置无关,只要函数声明在调用之前可见即可。
另外,还需要注意的是,函数重载并不改变函数的名称或参数列表。它只是允许你使用相同的函数名来定义多个具有不同参数列表的函数。在编译时,编译器会根据提供的参数来确定应该调用哪个版本的函数。在运行时,函数重载对程序的行为没有任何影响。
2. 内联函数(Inline Functions)
C++支持内联函数,这是一种建议编译器将函数调用替换为函数体本身的机制。这可以减少函数调用的开销,但可能会增加代码大小。在C语言中,内联函数不是语言的一部分,但编译器可能提供特定的扩展来支持它。
// C++ 示例
inline int max(int a, int b) {return (a > b) ? a : b;
}
内联函数的作用
内联函数(Inline Functions)在C++中主要起到以下作用:
-
减少函数调用的开销:当函数被声明为内联时,编译器会尝试在调用点将函数体直接插入,而不是进行常规的函数调用(即压栈、跳转、返回)。这样做可以消除函数调用的开销,从而提高程序的执行效率。对于小型且频繁调用的函数,这种开销减少尤为显著。
-
提高代码执行效率:由于内联函数在调用点直接插入函数体,可以减少因函数调用而产生的额外开销,如参数传递、栈帧创建和销毁等。因此,内联函数可以提高代码的执行效率。
-
消除函数调用的副作用:在某些情况下,函数调用可能会产生副作用,如修改全局变量或静态变量的值。而内联函数可以避免这种副作用,因为其在编译时展开,不会进行实际的函数调用。
-
支持类中的成员函数:在面向对象编程中,类的成员函数经常需要被频繁调用。将类的成员函数声明为内联函数可以减少因函数调用而产生的额外开销,从而提高程序的性能。此外,内联函数还可以保证类的封装性和隐藏性,因为只有在类的内部才能看到函数的实现细节。
-
提高可读性:对于某些简单的函数,将其声明为内联函数可以使代码更加紧凑和易于阅读。这是因为内联函数在调用点直接插入函数体,可以避免过多的函数调用和跳转,使代码结构更加清晰。
-
优化性能:在某些情况下,编译器可能会根据上下文和性能分析的结果自动将某些函数内联化。即使这些函数没有被显式声明为内联函数,编译器也会根据性能优化的需要进行内联展开。这进一步体现了内联函数在优化性能方面的作用。
需要注意的是,虽然内联函数可以提高程序的执行效率,但过度使用内联函数可能会导致代码膨胀和降低缓存效率。因此,在编写和使用内联函数时应该权衡利弊,根据具体情况进行选择。同时,也需要注意编译器对内联函数的支持程度和限制条件。
内联函数的限制
-
函数体复杂性:
- 内联函数的函数体不能含有复杂的结构控制语句,如
while
、for
、do-while
、switch
等循环和条件语句。如果内联函数中包含这些复杂的控制语句,编译器通常会将其视为普通函数处理,不进行内联展开。 - 递归函数不能被声明为内联函数,因为递归函数需要函数调用栈的支持,而内联函数在编译时展开,不保留函数调用栈信息。
- 内联函数的函数体不能含有复杂的结构控制语句,如
-
函数体大小:
- 内联函数通常适用于小型函数,如1-5行代码的小函数。过大的函数体可能会导致代码膨胀,降低程序的执行效率。
-
不能包含特定语句:
- 内联函数中不能说明数组(虽然这不是绝对的,但某些编译器可能会有限制)。
- 内联函数中不能有过多的条件判断语句,因为这会降低内联的效果。
- 不能对函数进行取址操作,因为内联函数没有独立的函数地址。
-
定义位置:
- 为了确保内联函数在所有调用它的地方都能被正确展开,通常需要将内联函数的定义放在头文件中。
-
编译器建议性:
- 内联函数是建议性的,而非强制性的。即使函数被声明为内联,编译器也有权选择忽略这个建议,不将函数内联化。这通常发生在函数体过大、过于复杂,或者编译器认为内联化不会带来性能提升的情况下。
-
性能考虑:
- 虽然内联函数可以减少函数调用的开销,但过度使用内联函数可能会导致代码膨胀,降低缓存命中率,反而降低程序的运行效率。因此,在使用内联函数时应该权衡利弊,根据具体情况进行选择。
综上所述,内联函数虽然可以提高程序的运行效率,但也有一些限制和需要注意的地方。在编写和使用内联函数时,应该根据具体情况进行权衡和选择。
3. 引用参数(Reference Parameters)
C++支持引用参数,允许函数直接操作传递给它的变量的原始数据,而不是其副本。这可以避免不必要的复制操作,提高效率。在C语言中,你只能通过指针来模拟这种行为。
// C++ 示例
void modify(int& x) { // 引用参数x = 10;
}int main() {int y = 5;modify(y); // y 的值现在为 10return 0;
}
4. 默认参数(Default Parameters)
在C++中,可以为函数参数提供默认值。如果在调用函数时没有提供这些参数的值,则使用默认值。这在C语言中是不可能的。
// C++ 示例
void greet(std::string name = "World") {std::cout << "Hello, " << name << "!" << std::endl;
}int main() {greet(); // 输出 "Hello, World!"greet("Alice"); // 输出 "Hello, Alice!"return 0;
}
默认参数
默认参数是C++中函数的一种特性,允许在函数调用时省略某些参数,此时将使用这些参数的默认值。以下是关于默认参数的详细解释:
-
定义与使用:
- 默认参数指的是在函数声明时给函数参数指定一个默认值。
- 如果调用函数时没有给这个参数传入实参,则使用默认值;如果传入了实参,则替换掉默认值。
-
语法规则:
- 默认参数只能从最右侧变量依次赋值,即如果一个参数有默认值,则它右边的所有参数都必须有默认值。
- 当函数的声明和实现分开时,需要在声明时指定默认值,实现时不能再次指定。
-
示例:
假设我们有一个函数print_int
,它接受一个整型参数i
,并有一个默认值-1
:void print_int(int i = -1) {std::cout << "i=" << i << std::endl; }
调用这个函数时,我们可以选择是否传入参数:
print_int(); // 输出:i=-1 print_int(10); // 输出:i=10
-
注意事项:
- 不要过度依赖默认参数,因为它们可能会使函数的使用变得模糊,增加维护成本。
- 当函数的参数较多,且很多参数都有默认值时,应该考虑使用其他方法(如结构体或类)来组织这些参数,以提高代码的可读性和可维护性。
-
优点:
- 提高了函数的灵活性,允许在函数调用时省略某些参数。
- 可以简化函数调用,减少代码冗余。
-
缺点:
- 如果过度使用默认参数,可能会导致函数接口变得复杂和难以理解。
- 如果在函数实现中再次指定了默认参数的值(当声明和实现分开时),将会导致编译错误。
-
与其他特性的关系:
- 默认参数可以与函数重载结合使用,以增加函数的多样性。
- 内联函数也可以使用默认参数,但内联函数的主要目的是提高程序性能,而默认参数则主要用于提高函数的灵活性。
占位参数
定义函数时,还可以给函数提供占位参数
- 占位参数只有参数类型,而没有参数名
- 在函数体内部无法使用占位参数
- 占位参数也可以指定默认参数
void func(int a,int = 0)
{cout<<a<<endl;
}
func(2);
5. 模板函数(Template Functions)
C++支持模板函数,允许你编写与类型无关的代码。编译器在编译时根据提供的类型信息实例化模板函数。这在C语言中是不可用的。
// C++ 示例
template <typename T>
T max(T a, T b) {return (a > b) ? a : b;
}int main() {int i = max(3, 5); // 调用 max<int>(3, 5)double d = max(3.14, 2.71); // 调用 max<double>(3.14, 2.71)return 0;
}
6. 成员函数(Member Functions)
在C++中,你可以定义类的成员函数,这些函数与类的特定实例相关联。这与C语言中的函数完全不同,C语言中的函数是全局的或静态的。
// C++ 示例
class MyClass {
public:int x;MyClass(int value) : x(value) {}// 成员函数void printValue() {std::cout << "x 的值为: " << x << std::endl;}
};int main() {MyClass obj(10);obj.printValue(); // 输出 "x 的值为: 10"return 0;
}
这些只是C++函数相对于C语言函数的一些主要差异和新增功能。C++还提供了许多其他特性和功能,如异常处理、类和对象、继承、多态等,这些都使C++成为一种功能强大的编程语言。
相关文章:
从C语言到C++(五)
从C语言到C(五) 自动类型推导尾拖返回类型类型信息推导typeid1. 定义和基本作用2. 使用方法3. 注意事项4. 示例代码5. 关联概念:RTTI decltype基本用法示例注意事项总结 基于范围的增强for循环示例 1:使用数组示例 2:使…...
数据结构——栈(Stack)详解
1. 栈(Stack) 1.1 概念 栈:一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中数据元素遵循后进先出LIFO(Last In First Out)的原则 压栈&am…...
1.Element的table表高度自适应vue3+js写法
解决方法 在页面table上添加id,动态计算每页table的最大高度 ,将高度保存在store中,每次切换路由时进行计算。 文章目录 解决方法前言一、页面table使用二、store状态库1.引入库 效果 前言 提示:状态管理使用的是pinia,用法参考…...
联想电脑电池只能充到80%,就不在充电了,猛一看以为坏了,只是设置了养护模式。
现在电池管理模式有三种: 1)常规 2)养护 3)快充 好久没有用联想的电脑了,猛一看,咱充到了80%不充了,难道电池是坏的?我们要如何设置才可以让其充电到100%呢? 右下角…...
Unity接入PS5手柄和Xbox手柄以及Android平台的(以及不同平台分析)
Unity接入PS5手柄和Xbox手柄以及Android平台的(以及不同平台分析) 介绍Unity手柄小知识PC端和编辑器上的摇杆事件和滑动事件PS5手柄Xbox手柄北通手柄 安卓环境下(安卓手机或者安卓模拟器)PS5手柄Xbox手柄北通手柄 总结 介绍 最近…...
vue+java实现简易AI问答组件(基于百度文心大模型)
一、需求 公司想要在页面中加入AI智能对话功能,故查找免费gpt接口,最终决定百度千帆大模型(进入官网、官方文档中心); 二、主要功能列举 AI智能对话;记录上下文回答环境;折叠/展开窗口&#…...
刷代码随想有感(104):动态规划——01背包问题/二维dp数组
题干: 代码: #include<bits/stdc.h> using namespace std; int n,bagweight; void solve(){vector<int>weight(n, 0);vector<int>value(n, 0);for(int i 0; i < n; i){cin>>weight[i];}for(int j 0; j < n; j){cin>…...
Docker-Portainer可视化管理工具
Docker-Portainer可视化管理工具 文章目录 Docker-Portainer可视化管理工具介绍资源列表基础环境一、安装Docker二、配置Docker加速器三、拉取Portainer汉化版本镜像四、运行容器五、访问可视化界面 介绍 Portainer是一款开源的容器管理平台,它提供了一个直观易用的…...
SqlSugar 集成
1 关于 SqlSugar SqlSugar 是 .NET/C# 平台非常优秀的 ORM 框架,目前 Nuget 总下载突破 700K,Github 关注量也高达 3.2K,是目前当之无愧的国产优秀 ORM 框架之一。 SqlSugar 官方地址:果糖网 ( SqlSugar 官网 &#…...
MySQL Connector/C++ 和 MySQL Connector/ODBC 的区别
MySQL Connector/C++ 和 MySQL Connector/ODBC 是两种不同的数据库连接工具,它们各自有不同的特点和用途。以下是它们之间的一些主要区别: 1. **编程接口**: - MySQL Connector/C++ 提供了面向对象的编程接口,它是用C++编写的,提供了C++特有的类和对象来与MySQL数据库…...
Weevil-Optimizer象鼻虫优化算法的matlab仿真实现
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 Weevil-Optimizer象鼻虫优化算法的matlab仿真实现,仿真输出算法的优化收敛曲线,对比不同的适应度函数。 2.测试软件版本以及运行结果展示…...
Web前端项目-交互式3D魔方【附源码】
交互式3D魔方 3D魔方游戏是一款基于网页技术的三维魔方游戏。它利用HTML、CSS和JavaScript前端技术来实现3D效果,并在网页上呈现出逼真的魔方操作体验。 运行效果: 一:index.html <!DOCTYPE html> <html><head><…...
视频格式转换avi格式怎么弄?分享视频转换方法
视频格式转换avi格式怎么弄?AVI作为一种广泛支持的视频格式,能够在多种设备和播放器上顺畅播放,确保我们的视频内容能够无障碍地分享给朋友或上传至各大平台。其次,AVI格式通常具有较好的兼容性,能够避免格式转换过程中…...
UniRx 入门
Reactive X 是 Reactive Extensions 的缩写,一般简写为 Rx,最初是 LINQ 的一个扩展,由微软的团队开发,Rx 是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,支持大部…...
简单游戏制作——飞行棋
控制台初始化 int w 50; int h 50; ConsoleInit(w, h); static void ConsoleInit(int w, int h) {//基础设置//光标的隐藏Console.CursorVisible false;//舞台的大小Console.SetWindowSize(w, h);Console.SetBufferSize(w, h); } 场景选择相关 #region 场景选择相关 //声…...
等保一体机
等保一体机是面向等保场景推出的合规型安全防护产品。基于“一个中心,三重防护”的设计理念,通过内置全面、多样的安全能力,为政府、医疗、教育、企业等中小型客户提供快速合规、按需赋能的一站式等保合规解决方案。 等保一体机要求管理网络和…...
什么是寄存器文件(Register File)?
寄存器文件(Register File)是计算机系统中用于存储处理器操作数的小型、快速的存储单元集。它在 CPU 内部,提供极高的访问速度,通常用于存储临时数据、操作数和指令执行过程中的中间结果。 寄存器文件的组成和特点 寄存器集&…...
6月15号作业
使用手动连接,将登录框中的取消按钮使用第二中连接方式,右击转到槽,在该槽函数中,调用关闭函数 将登录按钮使用qt4版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin"࿰…...
零基础入门学用Arduino 第三部分(三)
重要的内容写在前面: 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后,整体感觉是很好的,如果有条件的可以先学习一些相关课程,学起来会更加轻松,相关课程有数字电路…...
Trusty qemu + android环境搭建详细步骤
下载源码 mkdir trusty cd trusty repo init -u https://android.googlesource.com/trusty/manifest -b master repo sync -j32 编译 ./trusty/vendor/google/aosp/scripts/build.py generic-arm64 查看编译结果 ls build-root/build-generic-arm64/lk.bin 安装运行依赖 …...
杀戮尖塔游戏
Java 你正在玩策略卡牌杀戮尖塔游戏,轮到你出牌,手里N张攻击卡,每张都需要花金币coust[i]和获得伤害dmager[i]。 最多花3金币能造成的最大伤害是多少? class Solution{public int calc(int[] cost, int[] dmager, N){int[][] db …...
Kubernetes (K8s) 和 Spring Cloud 的区别
Kubernetes (K8s) 和 Spring Cloud 是两种常用的云原生技术,它们在微服务架构和云计算领域中扮演着重要的角色。尽管两者都有助于开发和部署微服务,但它们的功能和目标存在显著差异。本文将详细讨论 Kubernetes 和 Spring Cloud 的区别,从它们…...
定个小目标之刷LeetCode热题(21)
这是道技巧题,利用了 (num - 1)% n 计算下标的形式来将数组元素与数组索引产生映射关系,代码如下,可以看下注释 class Solution {public List<Integer> findDisappearedNumbers(int[] nums) {int n nums.lengt…...
Oracle 打开钱包 ORA-28368: cannot auto-create wallet
ORA-28368: cannot auto-create wallet 开启钱包抱错,看下钱包信息 SQL> select * from v$encryption_wallet;WRL_TYPE -------------------- WRL_PARAMETER -------------------------------------------------------------------------------- STATUS ------…...
【麒麟虚拟机】NetworkManager没有运行
麒麟V10 建linux麒麟虚拟机,发现,网络没有配置 提示,NetworkManager没有运行。编辑联接也不能配置 解决方法,在终端输入命令: sudo systemctl start NetworkManager 启动以后,编辑连接选自动以太网&…...
vue之一键部署的shell脚本和它的点.bat文件、海螺AI、ChatGPT
MENU 前言vite.config.ts的配置deploy文件夹的其他内容remote.shpwd.txtdeploy.bat 前言 1、在src同级新建deploy.bat文件; 2、在src同级新建deploy文件夹,文件夹中新建pwd.txt和remote.sh文件; 3、配置好后,直接双击deploy.bat文…...
pg和oracle的区别
1、从功能上来说pg要比oracle数据库弱。 2、pg不支持索引组织表。 pg和oracle的相似之处: 1、使用共享内存的进程结构,客户端与数据库服务器建立一个连接后,数据库服务器就启动一个进程为这个连接服务。这与mysql的线程模型不一样。 2、p…...
Docker:在DockerHub上创建私有仓库
文章目录 Busybox创建仓库推送镜像到仓库 本篇开始要学习在DockerHub上搭建一个自己的私有仓库 Busybox Busybox是一个集成了三百多个最常用Linux命令和工具的软件,BusyBox包含了很多工具,这里拉取该镜像推送到仓库中: 安装 apt install …...
框架的使用
什么是框架? 盖房子,框架结构 框架结构就是房子主体,基本功能 把很多基础功能已经实现(封装了) 框架:在基础语言之上,对各种基础功能进行封装,方便开发者,提高开发效…...
Autosar-DEM诊断事件管理流程
文章目录 前言一、故障事件监控二、故障信息上报三、故障信息处理Event的使能条件四、故障信息存储五、故障系统降级关联文章:Autosar实践——DEM配置 前言 DEM全称“Diagnostic Event Management”,该模块是AUTOSAR架构中的BSW模块之一。谈到故障,我们首先会想到如何去监控…...
用电脑怎么做原创视频网站/网络推广网站排名
电动化、自动驾驶以及汽车电子业务,已经是传统汽车零部件制造商必须选择的道路。而在过去几年时间,博世、大陆、采埃孚等巨头已经率先进行战略调整。 近日,马瑞利(Marelli)公司宣布将对旗下面向未来新技术业务板块的负…...
网站被取消备案/微博推广平台
原标题:实现一个简单的模板引擎模板引擎,其实就是一个根据模板和数据输出结果的一个工具。我们要开发一个将模板文件转换成我们实际要使用的内容的工具,这个工具就是模板引擎。我们把模板文件里的内容当成字符串传入到模板引擎中,…...
网站建设公司一般多少钱/网络营销心得体会800字
题目描述 呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第ii层楼(1 \le i \le N)(1≤i≤N)上有一个数字K_i(0 \le K_i \le N)Ki(0≤Ki≤N)。电梯只有四个按钮:开,关…...
做公司网站棋牌/购买友情链接
今天说说以***者的角度去谈谈服务器被干掉后,我们该做的哪些防护和检查工作,高手的话都比较熟悉系统加固和安全的问题,对于我等初学者来说,没有做过从事过安全方面工作,所以只能从***者的角度去说说相对立的工作。因为…...
做企业官网需要多少钱/seo营销技巧培训班
小练习,小练习哈,直接上代码,上课上的太无聊了,来玩一玩vue来了~ <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"…...
WordPress情侣博客模板/东莞网站推广优化网站
文章来自:http://www.cnblogs.com/shawn-xie/archive/2012/08/15/2638480.html 一.安装在安装PhoneGap开发环境之前,需要按顺序安装以下工具:1.Java SDK java sdk,不安装的话不能正常安装Android SDK。安装成功检测:启…...