c17 新特性 字面量,变量,函数,隐藏转换等

导论

        c17新特性引入了许多新的语法,这些语法特性更加清晰,不像传统语法,语义飘忽不定,比如‘a’你根本不知道是宽字符还是UTF-8 字符。以及测试i++ ++i,最后结果到底是多少。这种问题很大情况是根据编译器的优化进行猜测,不同环境,得出不同结果。而c17对这些问题给出完美的解决方案!

字符字面量

理论

官方给出的语法:

  • 普通字符字面量: 'c-char'

  • UTF-8 字符字面量: u8'c-char'

  • UTF-16 字符字面量: u'c-char'

  • UTF-32 字符字面量: U'c-char'

  • 宽字符字面量: L'c-char'

  • 普通多字符字面量: 'c-char-sequence'

  • 宽字符多字符字面量: L'c-char-sequence'

不太懂??基础薄弱!!

  1. 普通字符字面量:

    • 形式: 'c-char'
    • 表示: 一个单个的普通字符字面量,通常为 8 位 ASCII 字符。
    • 类型: char
  2. UTF-8 字符字面量:

    • 形式: u8'c-char'
    • 表示: 一个单个的 UTF-8 编码的字符字面量。
    • 类型: char8_t (C++20 引入)
  3. UTF-16 字符字面量:

    • 形式: u'c-char'
    • 表示: 一个单个的 UTF-16 编码的字符字面量。
    • 类型: char16_t
  4. UTF-32 字符字面量:

    • 形式: U'c-char'
    • 表示: 一个单个的 UTF-32 编码的字符字面量。
    • 类型: char32_t
  5. 宽字符字面量:

    • 形式: L'c-char'
    • 表示: 一个单个的宽字符字面量。宽字符的大小由实现定义,通常为 16 位或 32 位。
    • 类型: wchar_t
  6. 普通多字符字面量:

    • 形式: 'c-char-sequence'
    • 表示: 一个字符序列,由多个普通字符组成。
    • 类型: 数组类型 char[N],其中 N 为字符序列的长度。
  7. 宽字符多字符字面量:

    • 形式: L'c-char-sequence'
    • 表示: 一个字符序列,由多个宽字符组成。
    • 类型: 数组类型 wchar_t[N],其中 N 为字符序列的长度。

这些不同类型的字符字面量主要有以下区别:

  1. 字符编码:

    • 普通字符为 8 位 ASCII 编码。
    • UTF-8、UTF-16 和 UTF-32 字符分别采用 UTF-8、UTF-16 和 UTF-32 编码。
    • 宽字符的编码由实现定义,通常为 16 位或 32 位。
  2. 表示范围:

    • UTF-8、UTF-16 和 UTF-32 字符可以表示更广泛的字符集,包括非 ASCII 字符。
    • 宽字符的表示范围由实现定义。
  3. 内存占用:

    • 普通字符和 UTF-8 字符占用 1 个字节。
    • UTF-16 字符占用 2 个字节。
    • UTF-32 字符和宽字符占用 4 个字节。

        选择合适的字符类型取决于您的具体需求。对于仅需要处理 ASCII 字符的场景,使用普通字符就足够了。如果需要支持更广泛的字符集,可以考虑使用 UTF-8、UTF-16 或 UTF-32 字符。如果需要与遗留代码兼容,或者需要处理宽字符的场景,则可以使用宽字符。 现在我们可以定义出适合的字符串类型,写出最佳的程序。

实践

普通字符字面量:
char c1 = 'a';
char c2 = '\n';
char c3 = '\x2a'; // 等同于 '*'UTF-8 字符字面量:
char8_t c1 = u8'a';
// char8_t c2 = u8'¢'; // 错误,¢无法用单个UTF-8码元表示
// char8_t c3 = u8'猫'; // 错误,猫无法用单个UTF-8码元表示
// char8_t c4 = u8'🍌'; // 错误,🍌无法用单个UTF-8码元表示UTF-16 字符字面量:
char16_t c1 = u'a';
char16_t c2 = u'¢';
char16_t c3 = u'猫';
// char16_t c4 = u'🍌'; // 错误,🍌无法用单个UTF-16码元表示UTF-32 字符字面量:
char32_t c1 = U'a';
char32_t c2 = U'¢';
char32_t c3 = U'猫';
char32_t c4 = U'🍌';宽字符字面量:
wchar_t wc1 = L'a';
wchar_t wc2 = L'¢';
wchar_t wc3 = L'猫';
wchar_t wc4 = L'🍌'; // 在Windows上,这可能是非法的普通多字符字面量:
int mc1 = 'ab'; // 实现定义的值
int mc2 = 'abc'; // 实现定义的值宽字符多字符字面量:
wchar_t wmc1 = L'ab'; // 实现定义的值

有关变量的新语法

变量的评估顺序

表达式的求值顺序:

  • C++ 标准没有规定表达式中各个子表达式的求值顺序,除了一些特定的情况。

  • 通常编译器可以自由选择求值顺序,只要最终结果与按照左到右的顺序求值一致。

        x = (++x, ++y); 传统cpp并没有标准的定义到底谁先执行,都是由编译器优化,这就会造成环境不同,效果不同,争的你死我活。现在c17是这样解决的。

C++ 标准库中的 std::evaluatestd::as_const 这两个工具函数:

  1. std::evaluate (C++23):

    • 功能: 强制求值一个表达式,确保其副作用按照预期顺序发生。

    • 声明: template<class T> constexpr T&& evaluate(T&& t) noexcept;

    • 使用:

      int x = 0, y = 0;
      x = (++x, ++y); // 存在顺序未定义,可能 x 或 y 先增加
      x = std::evaluate((++x, ++y)); // 确保 x 和 y 按从左到右的顺序增加
    • 作用: 帮助开发者明确表达式的求值顺序,避免由于未定义行为导致的bug。

  2. std::as_const (C++17):

    • 功能: 获取一个表达式的常量引用,避免意外修改。

    • 声明: template<class T> constexpr const T& as_const(T& t) noexcept;

    • 使用:

      std::string s = "hello";
      std::string_view sv = s; // 可能意外修改 s
      std::string_view sv = std::as_const(s); // 确保 sv 只能读取 s 的内容
    • 作用: 帮助开发者强制使用只读引用,防止无意中修改原对象。

        总之, std::evaluatestd::as_const 是 C++ 标准库提供的两个有用的工具函数,前者解决表达式求值顺序的问题,后者解决引用可能被意外修改的问题。开发者可以在需要时使用它们来编写更加健壮的代码。

ifswitch初始化

这种多说无益,直接看示例就明白了。

auto lambda = [](int x) {if (int y = x * x; y > 100) {return y;} else {return 0;}
};int result = lambda(11); // result 为 121auto lambda = [](char c) {switch (int x = c; x) {case 'a':return 1;case 'b':return 2;default:return 0;}
};int result = lambda('b'); // result 为 2

 结构化绑定声明 简化代码。

可以看我往期文章,在此简单举个例子

#include <iostream>
#include <tuple>int main() {std::tuple<int, char, std::string> t{42, 'a', "hello"};//变量的数量必须与复合类型的元素数量一致。auto [x, y, z] = t;std::cout << x << ", " << y << ", " << z << '\n'; // 输出: 42, a, helloreturn 0;
}

左值引用和右值引用

可以看我往期文章,就不再赘述,这是重中之重。

constexpr consteval 编译时求值

constexpr 和 consteval 是 C++11 和 C++20 引入的两个关键字,它们都用于在编译时执行计算,但是它们之间有一些区别:

  1. constexpr:

    • constexpr 表示该变量或函数在编译时就可以计算出它的值。
    • constexpr 函数可以在编译时执行,也可以在运行时执行。
    • 如果 constexpr 函数在编译时无法计算出结果,编译器会尝试在运行时执行该函数。
    • constexpr 可以用于变量、函数和类的成员函数。
  2. consteval:

    • consteval 是 C++20 引入的,它比 constexpr 更加严格。
    • consteval 函数必须在编译时就能计算出结果,不能在运行时执行。
    • 如果 consteval 函数在编译时无法计算出结果,编译器会报错。
    • consteval 只能用于函数,不能用于变量或类的成员函数。

举例

constexpr 变量
constexpr int x = 42;
constexpr std::array<int, 3> arr = {1, 2, 3};constexpr 构造函数
struct Point {constexpr Point(int x, int y) : x(x), y(y) {}int x, y;
};
constexpr Point p(1, 2); // 在编译时创建 p 对象consteval关键字
consteval int square(int x) {return x * x;
}
constexpr int y = square(3); // 在编译时计算出 y = 9

总的来说:

  • constexpr 是一种"可能在编译时计算"的函数或变量,而 consteval 是一种"必须在编译时计算"的函数。
  • constexpr 提供了更大的灵活性,但 consteval 提供了更严格的编译时计算保证。
  • 开发者应该根据具体需求选择使用 constexpr 还是 consteval如果一个函数在编译时就能计算出结果,使用 consteval 更合适;如果需要在运行时也能正常执行,使用 constexpr 更合适。

任意类型变量 any variant

variant 编译期

std::variant 是 C++17 引入的一个非常有用的类型,它可以表示一个在多个类型之间进行选择的值。它提供了一种安全和高效的方式来处理可能出现的多种类型。

以下是 std::variant 的一些主要特点:

  1. 可以包含多种类型: std::variant 可以存储不同类型的值,这些类型由开发者在定义 std::variant 时指定。

  2. 类型安全: 与使用 void* 或者联合(union)相比, std::variant 提供了更好的类型安全性。它可以在编译时就检查访问是否合法,从而避免运行时错误。

  3. 访问安全: std::variant 提供了多种安全的访问方式,如 std::getstd::visit 等,可以确保在访问时不会出现未定义行为。

  4. 无需手动内存管理: std::variant 会自动管理其包含的值的生命周期,开发者不需要手动分配或释放内存。

any  运行期

std::any 是 C++17 引入的一个很有用的类型,它可以用来存储和传递任意类型的值。它提供了一个安全和高效的方式来处理动态类型的数据。

以下是 std::any 的一些主要特点:

  1. 可以存储任意类型的值: std::any 可以存储任何类型的值,包括基本数据类型、自定义类型、数组、指针等。

  2. 类型安全: 与使用 void* 相比, std::any 提供了更好的类型安全性。它会在运行时检查访问是否合法,从而避免未定义的行为。

  3. 无需手动内存管理: std::any 会自动管理其包含的值的生命周期,开发者不需要手动分配或释放内存。

  4. 支持赋值和拷贝: std::any 支持赋值和拷贝操作,这使得它可以很方便地在代码中传递和存储值。

示例

#include <iostream>
#include <any>
#include <variant>
#include <string>int main() {// 使用 std::anystd::any anyValue = 42;std::cout << "std::any value: " << std::any_cast<int>(anyValue) << std::endl;anyValue = std::string("hello");std::cout << "std::any value: " << std::any_cast<std::string>(anyValue) << std::endl;// 使用 std::variantstd::variant<int, std::string> variantValue = 42;std::cout << "std::variant value: " << std::get<int>(variantValue) << std::endl;variantValue = std::string("hello");std::cout << "std::variant value: " << std::get<std::string>(variantValue) << std::endl;return 0;
}

anyvariant区别

std::anystd::variant 都是 C++17 引入的非常有用的类型,但它们在功能和使用场景上有一些区别:

  1. 存储类型:

    • std::any 可以存储任意类型的值,包括自定义类型、数组、指针等

    • std::variant 只能存储在定义时指定的有限个类型中的一种

  2. 类型安全:

    • std::any 提供了运行时类型检查,通过 std::any_cast 访问时会检查类型是否匹配,不匹配则抛出 std::bad_any_cast 异常。

    • std::variant 则是在编译时就确定了可能存储的类型,通过 std::get 等函数访问时也可以在编译时检查类型是否匹配。

  3. 访问方式:

    • std::any 通过 std::any_cast 进行访问,需要显式指定类型。

    • std::variant 可以使用 std::getstd::visit 等多种方式进行访问。

  4. 使用场景:

    • std::any 适用于需要处理动态类型数据的场景,如插件系统、配置文件解析等

    • std::variant 则更适用于在有限的几种类型之间进行选择的场景,如函数重载、状态机等。

隐藏转换

这个模块可谓是本文的重点,坑点是最多的。

临时对象具体化 抛砖

        在 C++ 中,临时对象的具体化是一个非常重要的概念。临时对象是在表达式求值过程中创建的短暂对象,它们通常会在表达式结束后被销毁。

std::string getStr() {return "hello";
}
std::string s = getStr(); // 临时对象被具体化并赋值给s
在这个例子中, getStr() 函数返回一个临时的 std::string 对象,该对象会在 main()
函数中被具体化并赋值给 s。int x = 1, y = 2;
int z = x + y; // 临时对象被具体化并赋值给z
在这个例子中,x + y 表达式创建了一个临时的 int 对象,该对象会被具体化并赋值给 z。std::function<int(int)> get_lambda() {return [](int x) { return x * x; };
}
auto square_lambda = get_lambda();
int result = square_lambda(5); // 结果是 25在这个例子中:
1. `get_lambda()` 函数返回一个 lambda 表达式。
2. 这个 lambda 表达式产生了一个临时的 lambda 对象。
3. 这个临时的 lambda 对象被用于初始化 `square_lambda` 变量。
这个临时的 lambda 对象就是通过"临时对象具体化"的过程产生的。编译器会确保这个临时对象的生命周期足够长,以满足初始化 `square_lambda` 的需求。

保证拷贝省略 引玉

        保证拷贝省略(Guaranteed Copy Elision, GCE)并不是 C++17 引入的新特性,它实际上是在 C++11 中引入的。

  C++11中引入了以下几种情况下的拷贝省略:

  1. 返回值优化(RVO):

    • 当函数返回一个局部对象时,编译器可以直接在调用方的位置构造该对象,而无需进行拷贝。
  2. 移动语义优化:

    • 当返回一个临时对象时,编译器可以使用移动构造函数而不是拷贝构造函数
  3. 构造函数参数优化:

    • 当构造函数的参数是一个临时对象时,编译器可以直接在目标位置构造该对象,而无需进行拷贝。

C++17进一步扩展了拷贝省略的范围,增加了以下几种情况:

  1. 无参数构造函数拷贝省略:

    • 当函数返回一个局部对象,且该对象没有参数的构造函数时,编译器可以直接在调用方的位置构造该对象,而无需进行拷贝。
  2. 聚合类型拷贝省略:

    • 当函数返回一个聚合类型(如数组或结构体)的局部对象时,编译器可以直接在调用方的位置构造该对象,而无需进行拷贝。

总的来说,C++11和C++17中的拷贝省略优化可以显著提高程序的性能,减少不必要的拷贝操作。编译器会自动进行这些优化,开发者无需手动干预。

性能优化巅峰   

先举个例子

#include <iostream>class Noisy {
public:Noisy() { std::cout << "Noisy object constructed at " << this << '\n'; }Noisy(const Noisy& other) {std::cout << "Noisy object copy-constructed at " << this << '\n';}Noisy(Noisy&& other) noexcept {std::cout << "Noisy object move-constructed at " << this << '\n';}Noisy& operator=(const Noisy& other) {if (this != &other) {std::cout << "Noisy object copy-assigned at " << this << '\n';}return *this;}Noisy& operator=(Noisy&& other) noexcept {if (this != &other) {std::cout << "Noisy object move-assigned at " << this << '\n';}return *this;}~Noisy() {std::cout << "Noisy object destructed at " << this << '\n';}
};Noisy f(){// c11传统调用 创建一个临时 Noisy 对象,然后将其拷贝构造或移动构造到 v 中    // c17 编译器可以直接在 v 上构造 Noisy 对象,省略掉不必要的拷贝/移动操作。 称为(since C++17) "保证拷贝省略"Noisy v = Noisy();   //注意这里没有任何函数调用!!! 它是怎么做到给返回值给变量v赋值的??
/*
解答:
1.编译器识别到 Noisy v = Noisy(); 是一个直接初始化语句。 
2.它会在 v 的位置直接构造一个 Noisy 对象(Noisy v),而不是先创建一个临时对象,然后再拷贝或移动到 v 中。
3.这个构造过程会调用 Noisy 类的默认构造函数,输出 "Noisy object constructed at 0x[地址]"。
4.最终,v 就直接成为一个 Noisy 类型的对象,不需要经过任何拷贝或移动操作。
*/ return v; 
}void g(Noisy arg)
{std::cout << "&arg = " << &arg << '\n';
}int main()
{// c11  会执行一次拷贝或移动操作,将 v 的内容复制或移动到返回值中。//C++17引入命名返回值优化( NRVO)允许编译器直接在返回值位置构造对象(不调用构造函数),避免不必要的拷贝或移动。Noisy v = f();  //同理 f()返回值v 如何实现给v初始化的?/*
如果 f() 返回一个临时 Noisy 对象或者返回一个命名的 Noisy 对象(例如一个局部变量),编译器会尝试应用 RVO 和 NRVO 等优化,
尽量避免不必要的拷贝和移动操作。
编译器可以直接在 v 的位置构造这个返回的 Noisy 对象,避免任何拷贝或移动。
*/              std::cout << "&v = " << &v << '\n';g(f());// (since C++17)  "拷贝省略"
}

输出


constructed at 0x7fff1d765096    解释:代码行 Noisy v = Noisy(); 的调用
&v = 0x7fff1d765096
constructed at 0x7fff1d765097    解释:代码行 Noisy v = Noisy(); 的调用
&arg = 0x7fff1d765097destructed at 0x7fff1d765097
destructed at 0x7fff1d765096

 C++11 和 C++17 在这些优化上的差异:

  1. 临时变量的初始化:

    • C++11 及更早的版本中,Noisy v = Noisy(); 会先创建一个临时 Noisy 对象,然后将其拷贝或移动到 v 中。这会涉及一次构造和一次拷贝/移动操作。
    • C++17 引入了"保证拷贝省略"(Guaranteed Copy Elision, GCE)特性,编译器可以直接在 v 上构造 Noisy 对象,省略掉不必要的拷贝/移动操作。
  2. 函数返回值的优化:

    • C++11 及更早的版本中,return v; 会执行一次拷贝或移动操作,将 v 的内容复制或移动到返回值中。
    • C++17 引入的"命名返回值优化"(Named Return Value Optimization, NRVO)允许编译器直接在返回值位置构造对象,避免不必要的拷贝或移动。
  3. 函数参数的传递:

    • C++11 及更早的版本中,g(f()); 会先创建一个临时 Noisy 对象,然后将其拷贝或移动到 arg 中。
    • C++17 的"拷贝省略"(Copy Elision)特性允许编译器直接在 arg 上构造 Noisy 对象,避免不必要的拷贝或移动。

 上列的例子,应该能让读者更清楚的对c17”保证拷贝省略“进一步的理解,最后我们在整理一下思路,

临时变量的初始化: Noisy v = Noisy()  -> Nosiy v(); 
函数返回值的优化: Noisy v = {Noisy v; return v;} -> Nosiy v(); 
函数参数的传递:主函数 nrvo优化:
Noisy v = f(); -> 
Noisy v = {Noisy v = Noisy();  return v; }->   //临时变量初始化的优化
Noisy v = {Noisy v();  return v; } -> 
Noisy v = {return v} ->                      //函数返回值的优化
Noisy v = Noisy() ->  
Noisy v;g(f())
g(Noisy arg = {Noisy v = Noisy();  return v;})
g(Noisy arg =  {Noisy v();  return v;})
g(Noisy  arg )

隐式转换

C++ 隐式转换的内容总结如下:

  1. 隐式转换的顺序:

    • 标准转换序列 - 包括值转换和一些数值转换

    • 用户定义转换 - 通过单参数构造函数或转换函数进行

    • 可能的额外标准转换序列

  2. 值转换:

    • 左值到右值

    • 数组到指针

    • 函数到指针

    • 临时对象化 - 将右值转换为左值

  3. 整数提升:

    • 将小整数类型提升为 int 或 unsigned int

  4. 浮点提升:

    • float 转换为 double

  5. 数值转换:

    • 整数间转换

    • 浮点间转换

    • 浮点和整数间转换

    • 指针间转换

    • 指针到成员间转换

    • 布尔转换

  6. 限定符转换:

    • 在相似类型间添加或删除 const/volatile 限定符

  7. 上下文转换:

    • 在特定上下文中进行的隐式转换,如条件表达式、逻辑运算符等

举例

标准转换序列:
int x = 3.14; // float 到 int 的隐式转换用户定义转换:
class Rational {
public:Rational(int numerator, int denominator = 1) {// 用户定义的单参数构造函数}
};
Rational r = 5; // int 到 Rational 的隐式转换 5->Rational  因为没加explicit值转换:
int* p = new int[10]; 
int x = p[0]; // 数组到指针的隐式转换,然后左值到右值的隐式转换整数提升:
char c = 'a';int i = c; // char 提升到 int浮点提升:
float f = 3.14f;
double d = f; // float 提升到 double限定符转换:
const int* p = new int;
int* q = const_cast<int*>(p); // 从 const int* 到 int* 的转换上下文转换:
if (Rational r = 5) { // Rational 到 bool 的隐式转换// ...
}

总结

        总的来说,这篇文章全面介绍了C++17中的一些重要语法和概念变化,对于了解和掌握C++17的新特性很有帮助。文章内容丰富,逻辑清晰,可以作为C++17学习的良好参考资料。

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

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

相关文章

iframe 渲染请求到的 html (邮件预览), 避免样式污染 + 打印 iframe 邮件详情 + iframe 预览邮件时固定水平滚动条在视口底部

文章目录 iframe 渲染请求到的 html (邮件预览), 避免样式污染接上一条, 打印 iframe 邮件详情接上一条, iframe 预览邮件时, 要求固定水平滚动条在视口底部 iframe 渲染请求到的 html (邮件预览), 避免样式污染 背景: 之前弄了邮件系统, 但显示邮件内容时是直接 v-html , 导致…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的跳格子游戏(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

手写spring简易版本,让你更好理解spring源码

首先我们要模拟spring&#xff0c;先搞配置文件&#xff0c;并配置bean 创建我们需要的类&#xff0c;beandefito&#xff0c;这个类是用来装解析后的bean&#xff0c;主要三个字段&#xff0c;id&#xff0c;class&#xff0c;scop&#xff0c;对应xml配置的属性 package org…

理解 Kotlin 中的 crossinline 关键字

理解 Kotlin 中的 crossinline 关键字 Kotlin 提供了丰富的功能&#xff0c;用于开发简洁且富有表现力的代码。这些特性包括高阶函数和 Lambda 表达式&#xff0c;它们是 Kotlin 设计的核心部分。在使用这些构造时&#xff0c;您可能会遇到 crossinline 关键字。在本文中&#…

第二讲:NJ网络配置

Ethernet/IP网络拓扑结构 一. NJ EtherNet/IP 1、网络端口位置 NJ的CPU上面有两个RJ45的网络接口,其中一个是EtherNet/IP网络端口(另一个是EtherCAT的网络端口) 2、网络作用 如图所示,EtherNet/IP网络既可以做控制器与控制器之间的通信,也可以实现与上位机系统的对接通…

MySQL --- 表的操作

在对表进行操作时&#xff0c;需要先选定操作的表所在的数据库&#xff0c;即先执行 use 数据库名; 一、创建表 create table 表名( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎 ; 说明&#xff1a…

从零入门 AI for Science(AI+药物) #Datawhale AI 夏令营

使用平台 我的Notebook 魔搭社区 https://modelscope.cn/my/mynotebook/preset 主要操作 运行实例&#xff0c;如果有时长尽量选择方式二&#xff08;以下操作基于方式二的实例实现&#xff09; 创建文件夹&#xff0c;并重命名为 2.3siRNA 上传两个文件 到文件夹&#…

LC 128.最长连续序列

128.最长连续序列 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a; nums [100,4,200,1,3,2]…

go标准库---net/http服务端

1、http简单使用 go的http标准库非常强大&#xff0c;调用了两个函数就能够实现一个简单的http服务&#xff1a; func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) func ListenAndServe(addr string, handler Handler) error handleFunc注册一个路…

BGP路由反射器

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

LabVIEW做二次开发时应该注意哪些方面?

在使用LabVIEW进行二次开发时&#xff0c;以下几个方面需要特别注意&#xff1a; 需求明确化&#xff1a; 确认并详细记录客户的需求&#xff0c;明确系统的功能、性能、可靠性等要求。制定详细的需求文档&#xff0c;并与客户反复确认&#xff0c;避免后期的需求变更和误解。 …

【Android】数据存储方案——文件存储、SharedPreferences、SQLite数据库用法总结

文章目录 文件存储存储到文件读取文件 SharedPreferences存储存储获取SharedPreferences对象Context 类的 getSharedPreferences() 方法Activity 类的 getPreferences() 方法PreferenceManager 类中的 getDefaultSharedPreferences() 方法 示例 读取记住密码的功能 SQLite数据库…

4.Java Web开发模式(javaBean+servlet+MVC)

Java Web开发模式 一、Java Web开发模式 1.javaBean简介 JavaBeans是Java中一种特殊的类&#xff0c;可以将多个对象封装到一个对象&#xff08;bean&#xff09;中。特点是可序列化&#xff0c;提供无参构造器&#xff0c;提供getter方法和setter方法访问对象的属性。名称中…

JAVA代码审计JAVA0基础学习(需要WEB基础知识)DAY2

JAVA 在 SQL执行当中 分为3种写法&#xff1a; JDBC注入分析 Mybatis注入分析 Hibernate注入分析 JDBC 模式不安全JAVA代码示例部分特征 定义了一个 sql 参数 直接让用户填入id的内容 一个最简单的SQL语句就被执行了 使用安全语句却并没有被执行 Mybatis&#xff1a; #…

【MetaGPT系列】【MetaGPT完全实践宝典——多智能体实践】

目录 前言一、智能体1-1、Agent概述1-2、Agent与ChatGPT的区别 二、多智能体框架MetaGPT2-1、安装&配置2-2、使用已有的Agent&#xff08;ProductManager&#xff09;2-3、多智能体系统介绍2-4、多智能体案例分析2-4-1、构建智能体团队2-4-2、动作/行为 定义2-4-3、角色/智…

PyTorch和TensorFlow概念及对比

PyTorch和TensorFlow是两个流行的深度学习框架&#xff0c;用于构建和训练机器学习和深度学习模型。它们各自有一些独特的特点和优点&#xff1a; 一 、PyTorch 动态计算图&#xff1a; PyTorch使用动态计算图&#xff08;Dynamic Computation Graph&#xff09;&#xff0c;…

【OpenCV C++20 学习笔记】调节图片对比度和亮度(像素变换)

调节图片对比度和亮度&#xff08;像素变换&#xff09; 原理像素变换亮度和对比度调整 代码实现更简便的方法结果展示 γ \gamma γ校正及其实操案例线性变换的缺点 γ \gamma γ校正低曝光图片矫正案例代码实现 原理 关于OpenCV的配置和基础用法&#xff0c;请参阅本专栏的其…

五、工厂方法模式

文章目录 1 基本介绍2 案例2.1 Drink 抽象类2.2 Tea 类2.3 Coffee 类2.4 DrinkFactory 抽象类2.5 TeaFactory 类2.6 CoffeeFactory 类2.7 Client 类2.8 Client 类运行结果2.9 总结 3 各角色之间的关系3.1 角色3.1.1 Product ( 抽象产品 )3.1.2 ConcreteProduct ( 具体产品 )3.1…

生物信息学新突破:在英特尔 Gaudi 2 上实现 ProtST 蛋白质语言模型加速

引言 随着人工智能技术的快速发展&#xff0c;蛋白质结构预测和语言模型在生物信息学领域扮演着越来越重要的角色。ProtST作为一种新兴的蛋白质语言模型&#xff0c;其性能在英特尔 Gaudi 2 加速器的助力下得到了显著提升。本文将探讨如何利用英特尔 Gaudi 2 加速 ProtST 模型…

哈希表相关的力扣题和讲解和Java、C++常用的数据结构(哈希法)

20240725 一、什么时候适用什么样的结构。1.java中1.1 HashSet&#xff1a;1.2 TreeSet&#xff1a;1.3 LinkedHashSet&#xff1a;1.4 HashMap&#xff1a;1.5 TreeMap&#xff1a;1.6 LinkedHashMap&#xff1a;1.7 总结 2. c中2.1 std::unordered_set&#xff1a;2.2 std::s…