探索C++14新特性:更强大、更高效的编程

news2024/9/24 9:26:07

探索C++14新特性:更强大、更高效的编程

C++14并没有太大的改动,就连官方说明中也指出,C++14相对于C++11来说是一个比较小的改动,但是在很大程度上完善了C++11,所以可以说C++14就是在C++11标准上的查漏补缺。

C++14在2014年8月18日正式批准宣布,同年12月15日正式发布release版本。本文中将就变动部分做一个总结,有需要改进和提升的地方希望大家批评指正。

1、引言

1.1新的语言特性

  • 变量模板
  • 泛型 lambda
  • lambda 初始化捕获
  • 新建/删除省略
  • 放宽对 constexpr 函数的限制
  • 二进制文字
  • 数字分隔符
  • 函数的返回类型推导
  • 具有默认非静态成员初始值设定项的 聚合类。

1.2新库功能

  • std::make_unique

  • std::shared_timed_mutex 和 std::shared_lock

  • std::整数序列

  • 标准::交换

  • std::引用

  • 以及对现有图书馆设施的许多小改进,例如

    • 某些算法的两范围重载

    • 类型特征的类型别名版本

    • 用户定义的basic_string、持续时间和复杂的文字

    • ETC。

2、变量模板

在C++11 及之前,我们只有针对类和函数的模板。C++14 中,新增了变量模板:

template<class T>
constexpr T pi = T(3.1415926535897932385L);
template<class T>
T circular_area(T r)
{
	return pi<T> *r * r;
}

变量模板同样可以在类变量中使用:

template<class T>
class X {
	static T s;
};
template<class T>
T X<T>::s = 0;

X<int> x_int;
X<float> x_float;

int main() {
    int value_int = X<int>::s;       // 获取 int 类型的静态成员变量值
    float value_float = X<float>::s; // 获取 float 类型的静态成员变量值

    // ...
    return 0;
}

类似函数和类模板,当变量模板被引用时,则会发生实例化。

3、lambda 表达式的新增功能

3.1 泛化

支持在 lambda 表达式中使用 auto 定义变量类型:这一特性允许 Lambda 的形参或者内部变量的类型由编译器自动推导,而不必显式指定。

#include <iostream>
#include <algorithm>

int main() {
    // Lambda 表达式 glambda,用于输出元素
    auto glambda = [](auto& a) { std::cout << a << " "; };
    int a[] = { 4, 2, 6, 3, 7, 5 };
    // 使用 for_each 算法遍历数组,并对每个元素调用 Lambda 表达式 glambda
    std::for_each(a, a + sizeof(a) / sizeof(int), glambda);
    std::cout << std::endl;
    return 0;
}

3.2 对捕获的变量和引用进行初始化

include <iostream>
using namespace std;
int main()
{
	int x = 4;
	auto y = [&r = x, x = x + 1]()->int
	{
		r += 2;
		return x * x;
	}(); 
	cout << "x = " << x << " y = " << y << endl;
}
// 输出结果:x = 6 y = 25

auto y = [&r = x, x = x + 1]() -> int { ... }(); 定义了Lambda表达式并立即调用。

  • [&r = x, x = x + 1]:捕获了变量 x,通过引用捕获了 r,同时对 x 进行了初始化,将 x 的值增加了1。
  • ()->int { r += 2; return x * x; }:Lambda表达式的主体,对捕获的变量进行操作。r 是通过引用捕获的,所以对 r 的修改会影响到外部的 x。Lambda表达式返回 x * x 的结果。

4、constexpr 函数可以包含多个语句

在 C++11 中,如果想使用 constexpr 方法,只能包含一个返回语句。

#include <iostream>
constexpr int square(int x) {
    return x * x;
}
int main() {
    constexpr int result = square(5); // 合法的 constexpr 函数调用
    // 在 C++11 中,下面的调用将导致编译错误
    // constexpr int invalidResult = []() {
    //     int sum = 0;
    //     for (int i = 1; i <= 5; ++i) {
    //         sum += i;
    //     }
    //     return sum;
    // }();
    std::cout << "Result: " << result << std::endl;
    return 0;
}

C++14 中,放宽了此要求,允许 constexpr 函数中声明变量,使用循环和条件语句等:

#include <iostream>
#include <cmath>
using namespace std;
constexpr bool isPrimitive(int number) {
	if (number <= 0) {
		return false;
	}
	for (int i = 2; i <= sqrt(number) + 1; ++i) {
		if (number % i == 0) {
			return false;
		}
	}
	return true;
}
int main() {
	cout << boolalpha << isPrimitive(102) << " " << isPrimitive(103);
	return 0;
}

需要注意的是,虽然C++14对constexpr函数的要求放宽了一些,但仍然有一些限制。例如,递归和复杂的控制流结构可能仍然无法在constexpr函数中使用。

在C++11中,我们一般需要通过递归来实现相同的功能:

constexpr bool isPrimitive(int number, int currentFactor, int maxFactor) {
	return currentFactor == maxFactor ? true : 
			(number % currentFactor == 0 ? false : 
				isPrimitive(number, currentFactor + 1, maxFactor));
}
constexpr bool isPrimitive(int number) {
	return number <= 0 ? false : isPrimitive(number, 2, sqrt(number) + 1);
}

5、整型字面量

5.1 二进制字面量

支持使用 0b 开头的一串数字作为二进制表示的整型:

int a = 0b10101001110; // 1358

5.2 数字分隔符

支持在数字中使用单引号进行分割(便于阅读)。在编译时,这些单引号会被忽略。

int a = 123'456'789; // 123456789

6、返回类型自动推导

在 C++14 中,我们可以使用 auto 作为函数返回值并且不需要指明其返回类型的推导表达式

int x = 1;
auto f() { return x; }
/* c++11
auto f() -> decltype(x) { return x; } 
*/

这种类型推导有一些限制:

  1. 相同类型的推导: 在一个函数中,所有的返回语句必须推导出相同的类型。

    int x = 1;
    auto f() { return x; }  // 合法
    
  2. 使用 {} 包裹的数据: 对于使用 {} 包裹的数据作为返回值时,无法推导其类型。

    auto g() { return {1, 2, 3}; }  // 不合法
    
  3. 虚函数和 coroutine 不能被推导: 虚函数和协程不能使用此类型推导。

  4. 函数模板中的类型推导: 函数模板中可以使用类型推导,但显式实例化和特化版本必须使用相同的返回类型描述符。

    template <typename T>
    auto h(T value) { return value; }
    
    template auto h<int>(int);  // 合法
    

这些限制是为了保证类型推导的一致性和可靠性。虽然C++14引入了更多的自动类型推导,但在一些情况下,显式指定返回类型仍然是必要的。

7、exchange

exchange 用于移动语义,可以使用指定的新值替换掉原值,并返回原值。其定义在C++20中被简单修改如下:

template<class T, class U = T>
constexpr // since C++20
T exchange(T& obj, U&& new_value)
{
    T old_value = std::move(obj);
    obj = std::forward<U>(new_value);
    return old_value;
}

其使用如下:

#include <iostream>
#include <vector>
#include <utility>
using namespace std;
int main() {
	vector<int> v = {5, 6, 7};
	std::exchange(v, { 1,2,3,4 });
	std::copy(begin(v), end(v), ostream_iterator<int>(cout, " "));
	cout << endl;
}

8、quoted

该类用于字符串转义的处理。使用 out << quoted(s, delim, escape) 的形式,可以将字符串 s 的转义格式写入输出流中;

使用 in >> quoted(s, delim, escape) 可以将输入流去除转义格式后写入字符串 s 中。其中,delim 指明了需要转义的字符,escape 指明了修饰该转移字符的字符:

#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
int main() {
	stringstream ss;
	string in = "String with spaces, and embedded \"quotes\" too";
	string out;
	auto show = [&](const auto& what) {
		&what == &in
			? cout << "read in     [" << in << "]\n"
			<< "stored as   [" << ss.str() << "]\n"
			: cout << "written out [" << out << "]\n\n";
	};
	ss << quoted(in); 
	show(in);
	ss >> quoted(out);
	show(out);
	ss.str(""); 
	in = "String with spaces, and embedded $quotes$ too";
	const char delim{ '$' };
	const char escape{ '%' };
	ss << quoted(in, delim, escape);
	show(in);
	ss >> quoted(out, delim, escape);
	show(out);
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

9、C++14 经常考到的知识点

9.1 C++14 引入了哪些新特性?

C++14 引入了一些新特性,包括但不限于以下内容:

  1. 通用Lambda表达式:允许在lambda函数中使用auto关键字来推导参数类型。
  2. 自动返回类型推导:允许使用auto关键字自动推导函数返回值类型。
  3. 初始化列表的泛型支持:可以使用auto关键字在初始化列表中推导元素类型。
  4. 带有二进制分隔符的整数字面量:可以在整数常量中使用单撇号作为分隔符,提高可读性。
  5. constexpr函数的扩展:constexpr函数可以包含更多操作,例如循环和条件判断。
  6. 变长参数模板(Variadic Templates)的改进:支持递归处理变长参数模板的展开。
  7. 返回void类型的lambda表达式:允许定义返回void类型的lambda函数。

9.2 C++14 中 auto 关键字的用法和限制是什么?

在 C++14 中,auto 关键字用于自动类型推导,可以根据初始化表达式的类型来确定变量的类型。它的使用和限制如下:

  1. 自动类型推导:使用 auto 关键字声明变量时,编译器会根据初始化表达式的类型自动推导出变量的类型。
    auto x = 42; // 推导为int型 auto name = “John”; // 推导为const char*型
  2. 声明时必须初始化:使用auto声明变量时,必须进行初始化。因为编译器需要根据初始化表达式来推导出变量的类型。
    auto y; // 错误,未初始化
  3. 可与引用结合使用:auto关键字可以与引用一起使用,从而推导出引用的类型。
    int a = 10; auto& ref = a; // 推导为int&型,ref是a的引用
  4. 不支持数组或函数指针:auto不能直接用于数组或函数指针的声明。但可以通过decltype结合auto来实现对数组或函数指针类型进行推导。
    int arr[] = {1, 2, 3}; auto arrRef = arr; // 错误,无法推导arr的数组类型 decltype(arr) arrType; // 使用decltype获取arr的数组类型并声明arrType void foo(); auto funcPtr = foo; // 错误,无法推导foo的函数指针类型 decltype(foo)* funcPtrType; // 使用decltype获取foo的函数指针类型并声明funcPtrType

需要注意的是,auto 在 C++14 中的用法和限制可能与之后的标准(如 C++17、C++20 等)有所不同,具体取决于编译器和所使用的标准版本。

9.3 C++14 中如何使用 Lambda 表达式?有什么改进?

在C++14中,使用Lambda表达式的语法与之前的C++版本相似。Lambda表达式是一种可以在代码中内联定义匿名函数的方式。

下面是一个使用Lambda表达式的示例:

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    // 使用Lambda表达式进行遍历打印
    std::for_each(numbers.begin(), numbers.end(), [](int num) {
        std::cout << num << " ";
    });
    return 0;
}

在 Lambda 表达式中,方括号 [] 用于捕获外部变量(可选)。小括号 ( ) 内指定参数列表(可选),箭头 -> 后面指定返回类型(可选)。

C++14 对于 Lambda 表达式有一些改进,其中最显著的改进是可以自动推导返回类型。这意味着你不需要显式地指定返回类型,编译器会根据表达式体来推断返回类型。

以下是一个示例:

auto lambda = [](int a, int b) {
    return a + b;
};

在上述示例中,我们没有显式指定返回类型,但编译器会自动推断出返回类型为整数(因为a和b都是整数)。

此外,在 C++14 中还引入了泛型 lambda,使得可以在 lambda 函数中使用 auto 关键字作为参数类型,更加灵活和方便。

9.4 C++14 对于 constexpr 关键字有何改进?

C++14 对于 constexpr 关键字进行了一些改进,使得其更加灵活和强大。在 C++11 中,constexpr只能用于表示常量表达式的函数和构造函数,而在 C++14 中,它还可以用于一些额外的情况。

首先,在 C++14 中,constexpr函数可以包含一些非常量表达式的逻辑,只要这部分逻辑在运行时不会执行即可。这意味着我们可以在constexpr函数内使用循环、条件语句等非常量表达式的控制流程。

其次,C++14引入了对变量模板(Variable Templates)的支持,并且允许将变量声明为constexpr。这样我们就可以定义并初始化一个编译期间可计算的常量变量。

此外,在 C++14 中,对于某些标准库类型(如数组、字符串等),它们也提供了更多的支持以便于使用在编译期间计算出来的常量值。

9.5 C++14 中提供了哪些新的标准库组件和功能?

C++14引入了一些新的标准库组件和功能,以下是其中的一些主要特性:

  1. std::make_unique:提供了在堆上创建 unique_ptr 对象的便捷方式。
  2. std::integer_sequence:支持编译时整数序列的操作,用于元编程。
  3. std::user_defined_literals:允许用户定义自己的字面量后缀,扩展了语言的表达能力。
  4. 通用 lambda 表达式:允许使用 auto 参数声明参数类型,使得 lambda 表达式更加灵活。
  5. 变长模板参数折叠(Variadic template parameter packs expansion):可以将多个参数打包传递给模板函数或类,并且可以对它们进行展开操作。
  6. std::experimental 命名空间:引入了一些实验性质的标准库组件,如 optional、any、string_view 等。

9.6 在 C++14 中,变长参数模板是如何使用的?

在 C++14 中,可以使用变长参数模板(Variadic Templates)来处理可变数量的函数参数。通过使用递归展开参数包的方式,可以灵活地处理任意数量的参数。

下面是一个示例:

#include <iostream>
// 递归终止条件:当没有剩余参数时停止递归
void printArgs() {
    std::cout << "All arguments have been printed." << std::endl;
}
// 可变参数模板:展开第一个参数并调用自身处理剩余参数
template<typename T, typename... Args>
void printArgs(T first, Args... args) {
    std::cout << "Argument: " << first << std::endl;
    printArgs(args...); // 递归调用自身处理剩余参数
}
int main() {
    printArgs(1, "Hello", 3.14, 'A');
    return 0;
}

输出结果:

Argument: 1
Argument: Hello
Argument: 3.14
Argument: A
All arguments have been printed.

在上述代码中,printArgs 是一个可变参数模板函数。它首先处理第一个传入的参数 first,然后递归地调用自身处理剩余的 args 参数。当所有参数都被展开并打印完毕后,最终会到达递归终止条件。

这种方式使得我们能够在编译时处理不同数量和类型的函数参数,并且可以灵活地进行操作。

9.7 在 C++14 中,是否允许在 lambda 函数内定义其他函数或类?

在 C++14 中,lambda 函数内是不允许定义其他函数或类的。Lambda 函数是一个匿名的函数对象,它通常用于简化代码,提供一种在局部范围内编写小型函数的方式。Lambda 函数本质上是一个闭包,它可以捕获外部作用域中的变量,并且具有与普通函数相似的行为。

然而,在 C++17 中引入了嵌套lambda的概念,使得在 lambda 函数内定义其他 lambda 函数成为可能。在这种情况下,内层的 lambda 函数可以访问外层 lambda 函数的变量。所以如果你想要在 C++14 中定义其他函数或类,建议将其定义在 lambda 之外的范围内。

9.8 C++14 是否支持原始字符串字面量(raw string literals)?如何使用它们?

是的,C++14 支持原始字符串字面量(raw string literals)。

原始字符串字面量可以用来表示包含特殊字符(例如转义序列和引号)的字符串,而无需使用转义符号。它们由R"delim(raw_characters)delim"的语法表示,其中delim可以是任何非空字符序列,并且在开始和结束位置上必须匹配。

以下是一个示例:

#include <iostream>
int main() {
    const char* str1 = R"(Hello \n World!)";
    std::cout << str1 << std::endl;  // 输出:Hello \n World!
    const char* str2 = R"###(This is a "quoted" string.)###";
    std::cout << str2 << std::endl;  // 输出:This is a "quoted" string.
    return 0;
}

在上面的示例中,我们使用了原始字符串字面量来创建包含特殊字符的字符串,而不需要使用额外的转义符号。

9.9 在 C++14 中,std::make_unique和std::make_shared这两个函数的作用是什么?

在 C++14 中,std::make_uniquestd::make_shared是用于创建智能指针的函数模板。

  • std::make_unique:用于创建一个std::unique_ptr对象,它拥有独占所有权的动态分配对象。这个函数接受参数并返回一个std::unique_ptr,它会自动管理内存释放。示例:
auto ptr = std::make_unique<int>(42);
  • std::make_shared:用于创建一个std::shared_ptr对象,它可以被多个指针共享的动态分配对象。这个函数接受参数并返回一个std::shared_ptr,它使用引用计数来管理内存释放。示例:
auto ptr = std::make_shared<int>(42);

这两个函数可以减少手动进行资源管理的工作量,并提供了更安全、更简洁的方式来处理动态分配对象。

9.10 C++14 引入了统一初始化语法(uniform initialization syntax),具体有哪些变化?

C++14 引入了统一初始化语法(uniform initialization syntax),它允许使用一种更统一和一致的方式进行初始化。具体的变化包括以下几个方面:

  1. 初始化列表(initializer list):可以使用花括号 {} 来初始化对象,无论是简单类型还是复杂类型。例如:
    int num{ 42 }; std::vector vec{ 1, 2, 3 };
  2. 自动类型推导:在使用统一初始化语法时,编译器可以自动推导出变量的类型。
    auto value{ 3.14 }; // 推导为 double 类型 auto str{ “Hello” }; // 推导为 const char[6] 类型
  3. 统一构造函数调用语法:通过统一初始化语法,可以直接调用类的构造函数进行对象的创建。
    class MyClass { public: MyClass(int value) { /* 构造函数实现 */ } // … }; MyClass obj{ 42 }; // 调用构造函数创建对象
  4. 空初始化:可以使用 {}() 进行空初始化,不再需要显式地指定默认值。
    int num{}; // 初始化为0 std::string str{}; // 初始化为空字符串

zer list):可以使用花括号 {} 来初始化对象,无论是简单类型还是复杂类型。例如:
int num{ 42 }; std::vector vec{ 1, 2, 3 };
2. 自动类型推导:在使用统一初始化语法时,编译器可以自动推导出变量的类型。
auto value{ 3.14 }; // 推导为 double 类型 auto str{ “Hello” }; // 推导为 const char[6] 类型
3. 统一构造函数调用语法:通过统一初始化语法,可以直接调用类的构造函数进行对象的创建。
class MyClass { public: MyClass(int value) { /* 构造函数实现 */ } // … }; MyClass obj{ 42 }; // 调用构造函数创建对象
4. 空初始化:可以使用 {}() 进行空初始化,不再需要显式地指定默认值。
int num{}; // 初始化为0 std::string str{}; // 初始化为空字符串

这些变化使得初始化更加灵活和一致,并且提供了更强大的类型推导能力。注意,在使用统一初始化语法时,要注意类型的精确匹配和可能的隐式转换。

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

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

相关文章

Qt篇——QChartView实现鼠标滚轮缩放、鼠标拖拽平移、鼠标双击重置缩放平移、曲线点击显示坐标

话不多说。 第一步&#xff1a;自定义QChartView&#xff0c;直接搬 FirtCurveChartView.h #ifndef FITCURVECHARTVIEW_H #define FITCURVECHARTVIEW_H #include <QtCharts>class FitCurveChartView : public QChartView {Q_OBJECTpublic:FitCurveChartView(QWidget *…

apk反编译修改教程系列---简单去除apk开屏广告【五】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…

算法学习—排序

排序算法 一、选择排序 1.算法简介 选择排序是一个简单直观的排序方法&#xff0c;它的工作原理很简单&#xff0c;首先从未排序序列中找到最大的元素&#xff0c;放到已排序序列的末尾&#xff0c;重复上述步骤&#xff0c;直到所有元素排序完毕。 2.算法描述 1&#xff…

Linux中项目部署步骤

安装jdk&#xff0c;tomcat 安装步骤 1&#xff0c;将压缩包&#xff0c;拷贝到虚拟机中。 通过工具&#xff0c;将文件直接拖到虚拟机的/home下 2&#xff0c;回到虚拟机中&#xff0c;查看/home下&#xff0c;有两个压缩文件 3&#xff0c;给压缩文件做解压缩操作 tar -z…

分享70个节日PPT,总有一款适合您

分享70个节日PPT&#xff0c;总有一款适合您 70个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1IRIKuFoGjQJ14OVkeW_mDQ?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

Nuxt3 使用 pinia 基础

官方文档 一、安装 pnpm add pinia/nuxt二、配置 添加到 nuxt.config.js 中的 modules &#xff08;Nuxt 3&#xff09;或 buildModules &#xff08;Nuxt 2&#xff09;&#xff1a; // Nuxt 2 export default {buildModules: [[pinia/nuxt, { disableVuex: true }]], } /…

MySQL-含json字段表和与不含json字段表查询性能对比

含json字段表和与不含json字段表查询性能对比 说明: EP_USER_PICTURE_INFO_2:不含json字段表 20200729json_test:含有json字段表 其中20200729json_test 标准ID、MANAGER_NO、PHONE_NO 为非json字段 data为json字段 2个表中MANAGER_NO、PHONE_NO都创建了各自的索引 测试…

拼多多电商平台API接口,获取拼多多实时准确数据,获取产品销量、价格,sku图片及sku库存数据演示

拼多多商品详情API接口的作用是让开发者可以获取拼多多平台上特定商品的详细信息&#xff0c;包括商品的标题、价格、图片、规格、参数以及店铺信息等。通过这个接口&#xff0c;开发者可以轻松地获取商品的原始数据&#xff0c;便于进行数据分析、价格比较、爬取等操作。这为电…

python和php语言编写大型爬虫那个更适用 ?

以我多年从事爬虫行业的经验来说&#xff0c;其实python和php两种语言都可以用于编写大型爬虫项目&#xff0c;但是因为Python语言简洁方便&#xff0c;第三方库相比有很多&#xff0c;数据处理能力也很强&#xff0c;所以受到大多数程序员的追捧。 Python和PHP都可以用于编写…

32位旧内核2038溢出time记录

项目中有使用arm32的机器 现在内核动不了 有个使用时间范围显示是2023-2123 int在32bit下的 2038危机诞生了。 下面在svn找到代码 优化了一下 供大家学习哈&#xff0c;废话不多说直接上家伙&#xff1a; 需要的函数自己抄 #pragma once #include <stdio.h> #include …

Java 并发编程面试题——Java 线程间通信方式

目录 1.✨Java 线程间有哪些通信方式&#xff1f;1.1.volatile 和 synchronized 关键字1.2.等待/通知机制1.2.1.概述1.2.2.经典范式 1.3.管道输入/输出流1.4.信号量 2.Thread.join() 有什么作用&#xff1f;它的使用场景是什么&#xff1f;3.Java 中需要主线程等待子线程执行完…

家用打印机品牌多,种类杂,那么如何挑选最适合的家用打印机

在购买最好的家用打印机时&#xff0c;你可能会寻找足够多功能的打印机来满足每个人的需求。你的家人可能需要复印文件签字&#xff0c;扫描精致的旧照片&#xff0c;或者在接到通知后立即打印长篇文章或报告。良好的扫描功能确保你可以快速高效地将工作数字化&#xff0c;而每…

工程化使用React

安装 首先全局安装 npm install create-react-app -g创建项目 create-react-app proName最基本的一个react工程化创建完成 项目目录

CRM:如何通过客户数据分析获得业务洞察?

客户数据分析&#xff0c;也称客户分析&#xff0c;是收集、组织和分析客户数据&#xff0c;以深入了解客户行为的过程。企业将利用这些数据来制定与营销、产品开发、销售等相关的业务决策。 通过客户分析&#xff0c;你可以做出简单的业务决策&#xff0c;比如找出投资回报率…

基于PaddleSeg开发的人像抠图web api接口

前言 基于PaddleSeg开发的人像抠图web api接口&#xff0c;提取官方代码&#xff0c;适配各种系统&#xff0c;通过api的接口进行访问。 环境要求 1、Python3.7以上 2、源码&#xff08;文章最后下载&#xff09; 源码结构 测试module.py中添加如下代码&#xff1a; if __na…

城市内涝监测如何防治

洪涝灾害是我国历史上主要自然灾害之一&#xff0c;由于我国大部分地区受季风气候影响和降水季节性分配和空间分布不平衡等因素&#xff0c;一些城市洪涝灾害易发多发&#xff0c;危及城市居民的生命财产安全&#xff0c;也影响城市安全运行和可持续发展。因此&#xff0c;城市…

SQL Sever 基础知识 - 数据筛选(1)

SQL Sever 基础知识 - 四、数据筛选 四、筛选数据第1节 DISTINCT - 去除重复值1.1 SELECT DISTINCT 子句简介1.2 SELECT DISTINCT 示例1.2.1 DISTINCT 一列示例1.2.2 DISTINCT 多列示例 1.2.3 DISTINCT 具有 null 值示例1.2.4 DISTINCT 与 GROUP BY 对比 第2节 WHERE - 过滤查询…

easyexcel的@NumberFormat源码解析

debug了一天&#xff0c;关键源码如下&#xff1a; com.alibaba.excel.write.executor.AbstractExcelWriteExecutor#converterAndSet 由于 NumberFormat 注解对应的字段肯定是 BigDecimal &#xff0c;所以肯定会走这一步 然后进行赋值&#xff0c;然后再之前给cell设置好了格…

linux部署前端页面(实战)

Linux基本命令&#xff08;学习笔记&#xff09;零基础入门linux系统运维_linux find exec rm_Z_Xshan的博客-CSDN博客 如果linux不熟可以看我之前写的入门教程 感谢支持&#xff01;&#xff01; 一、服务器 这里去购买云服务器&#xff0c;如果是练习可以用虚拟机&#xff…