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

探索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{}; // 初始化为空字符串

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软磁材料市场分析:我国产量约18万吨

软磁材料&#xff0c;指的是当磁化发生在Hc不大于1000A/m&#xff0c;这样的材料称为软磁体。典型的软磁材料&#xff0c;可以用最小的外磁场实现最大的磁化强度。软磁材料(soft magnetic material)具有低矫顽力和高磁导率的磁性材料。 主要应用于风电、电子、计算机、通信、医…

IT外包服务融合云计算:企业信息化发展的新阶段

IT外包服务和云计算是企业在发展过程中重点关注的对象&#xff0c;它们在不同的方面为企业的信息化建设提供有力的支持。而两者的融合与发展更是为企业带来了巨大的机遇和挑战。 IT外包服务与云计算的融合为企业带来的机遇 首先&#xff0c;IT外包服务与云计算的融合使企业能够…

AI助力智慧农业,基于YOLOv5全系列模型【n/s/m/l/x】开发构建不同参数量级农田场景下庄稼作物、杂草智能检测识别系统

紧接前文&#xff0c;本文是农田场景下庄稼作物、杂草检测识别的第二篇文章&#xff0c;前文是基于YOLOv3这一网络模型实现的目标检测&#xff0c;v3相对来说比较早期的网络模型了&#xff0c;本文是基于最为经典的YOLOv5来开发不同参数量级的检测端模型。 首先看下实例效果&a…

数字与数学高频问题

关卡名 数字与数学高频问题 我会了✔️ 内容 1.掌握数组实现加法的方法 ✔️ 2.掌握高精度计算的实现方法 ✔️ 3.掌握幂运算的技巧 ✔️ 1. 数组实现加法专题 数字加法&#xff0c;小学生都会的问题&#xff0c;但是如果让你用数组来表示一个数&#xff0c;如何实现加法…

百面嵌入式专栏(岗位分析)海康高级linux开发工程师分析

文章目录 一、岗位的介绍二、刨析2.1、掌握调试工具2.2、块设备相关知识 三、简历建议 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; &#x1f4e2;本篇我们将对海康高级linux开发工程师岗位进行分析 。 一、岗位的介绍 地点&#xff1a;上…

JS箭头函数

箭头函数 1. 基本语法 // // 一般函数const fn function() {console.log(123);}// 箭头函数const fn () > {console.log(123);}fn()const fn (x) > {console.log(x);}fn(1)// 只有一个形参的时候可以省略小括号const fn x > {console.log(x);}fn(1)// 只有一行代…

学习springcloud时遇到java: 找不到符号 符号: 方法 getPname()

学习springcloud时异常-java: 找不到符号 符号: 方法 getPname() 学习springcloud时&#xff0c;遇到获取实体类属性值时出现异常。 项目目前分为两个子模块&#xff0c;一个是实体类模块&#xff0c;另一个是应用层。 在查询数据后&#xff0c;打印pname属性时报错&#xff…

FIR IP 学习记录

工具&#xff1a; matlab filterdesigner 工具箱 vivado FIR IP核 实现&#xff1a; 1.matlab设计与测试 先用matlab设计目标滤波器&#xff0c;得到滤波器的抽头系数。 如图&#xff0c;根据需求选择 低通/高通/带通/带阻。 由于vivado用的是FIR IP核&#xff0c;所以设…

C++ 结构体详解

目录 结构体声明 结构体自引用 匿名结构体类型 结构体变量的定义与初始化 匿名结构体的定义与初始化 内存对齐 结构体传参 结构体声明 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 struct tag {member - list;//成员 };…

自定义构建jdk镜像

&#xff08;1&#xff09;准备jdk压缩包、创建Dockerfile文件 jdk压缩包、Dockerfile文件在同一目录&#xff0c;如下 Dockerfile文件内容如下 # 指定基础镜像 FROM centos:latest # 作者和电子邮件 MAINTAINER vinegar93 "vinegar93163.com" # 指定工作目录 WORK…

el-date-picker时间控制范围为过去时间不可选

<el-date-picker :picker-options"startPickerOptions()" value-format"yyyy-MM-dd HH:mm:ss" v-model"form.applyFixPlan" type"datetime" placeholder"选择日期时间"> </el-date-picker> 在method中定义star…

数据库管理-第123期 Oracle相关两个参数(202301205)

数据库管理-第123期 Oracle相关两个参数&#xff08;202301205&#xff09; 最近在群聊中看到俩和Oracle数据库相关的俩参数&#xff0c;一个是Oracle数据库本身的&#xff0c;一个是来自于Weblogic的&#xff0c;挺有趣的&#xff0c;本期研究一下。&#xff08;本期涉及参数…

记录一次浏览器报错Whitelabel Error Page

后端打包prod的时候错误打包成了dev,部署到服务器上导致访问静态资源的时候全部报这个错.

【CentOS】配置 Apache 服务

yum install httpd -y# 查看是否安装成功 httpd -v # 出现版本号表示成功# 启动服务 systemctl start httpd# 查看状态 systemctl status httpd # running 即可成功 ● httpd.service - The Apache HTTP ServerLoaded: loaded (/usr/lib/systemd/system/httpd.service; disable…

人才招聘信息网的设计与实现

摘 要 随着经济的高速发展&#xff0c;人才的流动也越来越频繁&#xff0c;怎样才能用最少的精力和时间来招聘人才的企业要求相一致&#xff0c;也让应聘人参加应聘是企业和个人都关心的问题。 本网站采用基于广域网的B/S结构平台&#xff0c;比C/S有更强的适用范围&#xff0…

漏洞复现--万户ezoffice wpsservlet任意文件上传

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

Linux基本指令(2.0)

周边知识&#xff1a; 1.Linux中&#xff0c; 一切皆文件 构建大文件 输入如下shell命令 i1; while [ $i -le 10000]; do echo "hello Linux $i"; let i; done 此时大文件已经创建在big.txt 此时我们发现cat查看无法查看开始内容 我们使用more 当占满一屏之后就不…

[adbd] adb添加密码登录SHELL

项目中设备为Linux&#xff0c;使用ADB进行调试&#xff0c;为了安全需要在adb shell时进行密码认证。 在此记录一下&#xff0c;防止遗忘~~~ 修改 system/core/adb/services.c 文件的登录shell为 /bin/login 这样就可以使用linux自带的认证服务 如果想强制指定某个用户进行登…

快手数仓面试题附答案

题目 1 讲一下你门公司的大数据项目架构&#xff1f;2 你在工作中都负责哪一部分3 spark提交一个程序的整体执行流程4 spark常用算子列几个&#xff0c;6到8个吧5 transformation跟action算子的区别6 map和flatmap算子的区别7 自定义udf&#xff0c;udtf&#xff0c;udaf讲一下…

嵌入式硬件和软件哪个好?

嵌入式硬件和软件哪个好? 嵌入式软硬件工程师哪个更有前途呢?一起来看看。 嵌入式是分为软硬件工程师的&#xff0c;首先我们先来看看嵌入式硬件工程师吧! 嵌入式硬件开发工程师主要编写嵌入式系统硬件总体方案和详细方案&#xff0c;要求理解嵌入式系统架构&#xff0c;有一…