C++中的函数组合:用std::function实现编程艺术

news2024/11/6 7:19:32

C++中的函数组合:用std::function实现编程艺术

  • 1. 引言
    • 1.1 C++中的函数式编程 (Functional Programming in C++)
    • 1.2 函数组合的概念和价值 (Concept and Value of Function Composition)
    • 1.3 std::function概述 (Overview of std::function)
  • 2. 如何在C++中实现函数组合 (Implementing Function Composition in C++)
    • 2.1 用std::function实现简单的函数组合 (Simple Function Composition using std::function)
    • 2.2 对复杂函数的组合操作 (Composition Operation for Complex Functions)
    • 2.3 函数组合与错误处理 (Function Composition and Error Handling)
  • 3. 函数组合的应用实例 (Application Examples of Function Composition)
    • 3.1 在算法中使用函数组合 (Using Function Composition in Algorithms)
    • 3.2 使用函数组合改进软件设计 (Improving Software Design with Function Composition)
    • 3.3 函数组合在现代C++编程中的角色 (The Role of Function Composition in Modern C++ Programming)
  • 4. 结语
    • 4.1 函数组合的优点与限制 (Advantages and Limitations of Function Composition)
      • 优点 (Advantages)
      • 限制 (Limitations)
    • 4.2 对函数式编程的思考 (Reflections on Functional Programming)
    • 4.3 对未来C++发展的展望 (Outlook for the Future Development of C++)

1. 引言

1.1 C++中的函数式编程 (Functional Programming in C++)

函数式编程(Functional Programming,简称FP)是一种编程范式,它将计算过程视为一系列数学函数的求值。这种范式强调程序的执行结果而非执行过程,避免了状态的改变和数据的变动。函数式编程具有一些独特的特性,如纯函数(Pure Function)、不可变性(Immutability)和函数作为一等公民(Function as First-Class Citizen)等。

C++是一种多范式编程语言,它支持过程式编程、面向对象编程,同时也支持函数式编程。C++11、C++14、C++17和C++20等新标准的引入,使得C++在函数式编程方面的能力得到了显著的提升。

在C++中,函数式编程的实现主要依赖于以下几个关键特性:

  1. Lambda表达式(Lambda Expressions):Lambda表达式是C++11引入的一种新特性,它允许在代码中定义匿名函数。Lambda表达式的引入使得C++程序员可以更方便地编写高阶函数(接受其他函数作为参数或返回函数的函数)。

  2. std::function:std::function是一个通用、多态的函数封装器。它的实例可以对任何可以调用的目标实体进行存储、复制和调用操作,这包括普通函数、Lambda表达式、函数指针和类的成员函数等。

  3. 智能指针(Smart Pointers):智能指针是一种对象,它像指针一样进行操作,但可以自动删除所指向的对象。智能指针在函数式编程中常用于管理函数创建的资源,避免资源泄漏。

  4. 模板元编程(Template Metaprogramming):模板元编程是一种在编译时进行计算的技术,它使用模板来生成编译时常量和代码。模板元编程在函数式编程中常用于实现复杂的编译时函数和算法。

以上特性的结合,使得C++能够实现高效、强大的函数式编程。在接下来的内容中,我们将深入探讨C++中函数式编程的实现和应用。

1.2 函数组合的概念和价值 (Concept and Value of Function Composition)

函数组合(Function Composition)是函数式编程中的一个核心概念,它指的是将两个或多个函数组合成一个新的函数,新函数的输出是由原函数按照一定的顺序依次计算得到的。在数学中,函数组合通常表示为 (f∘g)(x) = f(g(x)),这意味着函数g首先作用于输入x,然后函数f作用于g(x)的结果。

在C++中,函数组合可以通过多种方式实现,如使用函数指针、函数对象、Lambda表达式和std::function等。函数组合的实现需要考虑到函数的输入输出类型,以及函数执行可能出现的错误等因素。

函数组合的价值主要体现在以下几个方面:

  1. 代码复用:通过将小的、通用的函数组合成更复杂的函数,可以避免重复编写相似的代码,提高代码的复用性。

  2. 代码可读性:函数组合可以使代码的结构更清晰,更易于理解。每个小的函数都有明确的功能,通过查看函数的组合方式,可以快速理解代码的功能。

  3. 代码可维护性:由于函数组合是由一系列小的函数构成的,因此在修改代码时,只需要修改相关的小函数,而不需要修改整个大函数。这使得代码更易于维护。

  4. 代码可测试性:每个小的函数都可以单独进行测试,这使得代码的测试更为方便,也更容易保证代码的质量。

在接下来的内容中,我们将详细介绍如何在C++中实现函数组合,以及函数组合在实际编程中的应用。

1.3 std::function概述 (Overview of std::function)

std::function是C++11引入的一种新特性,它定义在<functional>头文件中。std::function是一个通用、多态的函数封装器,它的实例可以存储、复制和调用任何可复制构造的可调用目标,包括普通函数、Lambda表达式、绑定表达式、其他函数对象,以及类的成员函数和数据成员指针等。

std::function的存储的可调用对象被称为目标(target)。如果一个std::function不包含目标,那么它被称为空的。调用一个空的std::function的目标会导致抛出std::bad_function_call异常。

std::function满足复制构造和复制赋值的要求。它提供了一系列成员函数,包括构造函数、析构函数、赋值操作符、交换内容的函数等。此外,它还提供了operator bool成员函数用于检查是否包含目标,以及operator()成员函数用于调用目标。

std::function的使用需要注意一些问题。例如,当std::function的结果类型是引用时,如果它是从一个返回prvalue(纯右值)的函数或函数对象(包括没有尾随返回类型的Lambda表达式)初始化的,那么程序是不合法的,因为绑定返回的引用到临时对象是被禁止的。

在接下来的内容中,我们将详细介绍如何在C++中使用std::function实现函数组合,以及std::function在实际编程中的应用。

2. 如何在C++中实现函数组合 (Implementing Function Composition in C++)

2.1 用std::function实现简单的函数组合 (Simple Function Composition using std::function)

在C++中,我们可以使用std::function来实现函数组合。下面是一个简单的例子:

#include <iostream>
#include <functional>

// 定义两个简单的函数
double addOne(double x) { return x + 1; }
double multiplyByTwo(double x) { return x * 2; }

int main() {
    // 使用std::function封装函数
    std::function<double(double)> f1 = addOne;
    std::function<double(double)> f2 = multiplyByTwo;

    // 定义函数组合
    std::function<double(double)> f = [f1, f2](double x) { return f1(f2(x)); };

    // 测试函数组合
    std::cout << f(5) << std::endl;  // 输出12,因为(5*2)+1=12

    return 0;
}

在上面的代码中,我们首先定义了两个简单的函数addOnemultiplyByTwo,然后使用std::function封装了这两个函数。接着,我们定义了一个新的函数f,这个函数是addOnemultiplyByTwo的组合,它首先调用multiplyByTwo,然后将结果传递给addOne。最后,我们测试了这个函数组合,输入5,输出12,证明函数组合工作正常。

这个例子展示了如何使用std::function实现简单的函数组合。在实际编程中,我们可能需要处理更复杂的情况,如函数的输入输出类型不同,函数执行可能出现错误等。在下一节,我们将介绍如何处理这些复杂情况。

2.2 对复杂函数的组合操作 (Composition Operation for Complex Functions)

在实际编程中,我们可能需要处理更复杂的函数组合,如函数的输入输出类型不同,函数执行可能出现错误等。在这种情况下,我们可以使用std::function的多态性来处理不同类型的函数,同时使用异常处理机制来处理函数执行可能出现的错误。

下面是一个处理复杂函数组合的例子:

#include <iostream>
#include <functional>
#include <string>
#include <stdexcept>

// 定义两个复杂的函数
std::string addHello(const std::string& name) { return "Hello, " + name; }
int stringLength(const std::string& str) { return str.length(); }

int main() {
    // 使用std::function封装函数
    std::function<std::string(const std::string&)> f1 = addHello;
    std::function<int(const std::string&)> f2 = stringLength;

    // 定义函数组合
    std::function<int(const std::string&)> f = [f1, f2](const std::string& name) {
        std::string hello = f1(name);
        return f2(hello);
    };

    // 测试函数组合
    try {
        std::cout << f("World") << std::endl;  // 输出13,因为"Hello, World"的长度是13
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

在上面的代码中,我们首先定义了两个复杂的函数addHellostringLength,然后使用std::function封装了这两个函数。接着,我们定义了一个新的函数f,这个函数是addHellostringLength的组合,它首先调用addHello,然后将结果传递给stringLength。最后,我们测试了这个函数组合,输入"World",输出13,证明函数组合工作正常。

这个例子展示了如何使用std::function处理复杂的函数组合。在下一节,我们将介绍如何在函数组合中处理错误。

2.3 函数组合与错误处理 (Function Composition and Error Handling)

在实际编程中,函数执行可能会出现错误,如输入参数不合法,资源不足等。在函数组合中,我们需要考虑如何处理这些错误。C++提供了异常处理机制,我们可以使用这个机制来处理函数执行可能出现的错误。

下面是一个处理函数组合中的错误的例子:

#include <iostream>
#include <functional>
#include <stdexcept>

// 定义两个可能会抛出异常的函数
double divide(double x, double y) {
    if (y == 0) {
        throw std::invalid_argument("Divide by zero");
    }
    return x / y;
}

double addOne(double x) {
    if (x > 100) {
        throw std::overflow_error("Overflow");
    }
    return x + 1;
}

int main() {
    // 使用std::function封装函数
    std::function<double(double, double)> f1 = divide;
    std::function<double(double)> f2 = addOne;

    // 定义函数组合
    std::function<double(double, double)> f = [f1, f2](double x, double y) {
        double result = f1(x, y);
        return f2(result);
    };

    // 测试函数组合
    try {
        std::cout << f(10, 0) << std::endl;  // 抛出异常:Divide by zero
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    try {
        std::cout << f(100, 1) << std::endl;  // 抛出异常:Overflow
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

在上面的代码中,我们首先定义了两个可能会抛出异常的函数divideaddOne,然后使用std::function封装了这两个函数。接着,我们定义了一个新的函数f,这个函数是divideaddOne的组合,它首先调用divide,然后将结果传递给addOne。在调用函数组合时,我们使用try-catch语句来捕获可能出现的异常。

3. 函数组合的应用实例 (Application Examples of Function Composition)

3.1 在算法中使用函数组合 (Using Function Composition in Algorithms)

函数组合在算法中的应用是一个重要的概念。它涉及到如何将多个函数组合在一起,以实现更复杂的功能。这种方法在许多算法设计中都有应用,包括排序、搜索、图形算法等。

在C++中,函数可以被视为一种对象,可以被传递给其他函数,或者作为其他函数的返回值。这种特性使得函数组合成为可能。例如,我们可以创建一个函数,它接受一个函数作为参数,并返回一个新的函数,这个新的函数在调用时会首先调用输入的函数,然后对结果进行某种处理。

这种方式的一个优点是可以创建高度模块化的代码。每个函数都可以独立进行设计和测试,然后通过组合这些函数来创建更复杂的行为。这也使得代码更易于理解和维护,因为每个函数都有明确的责任。

函数组合也可以用于实现高阶函数,这是一种接受其他函数作为参数或返回其他函数的函数。高阶函数在许多算法设计中都有应用,包括映射(map)、过滤(filter)和折叠(fold)等操作。

例如,我们可以定义一个高阶函数map,它接受一个函数f和一个列表l作为参数。map函数会对列表l中的每个元素应用函数f,并返回结果列表。这种方式可以用于实现各种复杂的列表处理操作,而无需显式地编写循环。

函数组合在算法设计中的应用是一个深入的主题,涉及到许多高级的编程技巧和概念。通过学习和理解这个主题,可以提高我们的编程能力,使我们能够编写出更高效、更易于理解和维护的代码。

参考代码:

// 在Swift库中的应用
// 链接:https://github.com/apple/swift/blob/5cdd34aa9305175e8f63e5e2421bb8ebc9855ee5/lib/AST/RequirementMachine/RewriteSystem.h

// 在Milewski的"程序员的范畴论"中的应用
// 链接:https://github.com/hmemcpy/milewski-ctfp-pdf/blob/45db8d515abc095f6ab648450df37c5cb5d6d6af/src/content/1.2/types-and-functions.tex

// 在编程面试大学中的应用
// 链接:https://github.com/jwasham/coding-interview-university/blob/4b53c748b3658ae271c04cf79c6b4fd03d2a6e37/README.md

以下是GitHub的一段代码片段,它演示了C++中的函数组合:

template <typename F, typename G>
auto compose(F f, G g) {
    return [f, g](auto x) { return f(g(x)); };
}

int main() {
    auto add_one = [](int x) { return x + 1; };
    auto square = [](int x) { return x * x; };

    auto add_one_and_square = compose(square, add_one);

    std::cout << add_one_and_square(5) << std::endl;  // prints 36
}

在本例中,Compose是一个函数,它接受两个函数f和g,并返回一个新函数,当调用该函数时,将g应用于其参数,然后将f应用于结果。这是一个用C++编写函数的简单示例。ADD_ONE_AND_Square函数是ADD_ONE和Square的组合,因此当使用参数调用它时,它会将1加到参数上,然后将结果平方。

3.2 使用函数组合改进软件设计 (Improving Software Design with Function Composition)

函数组合在软件设计中的应用,可以带来许多优势,包括代码的简洁性、可读性和可维护性的提高。通过将复杂的操作分解为一系列简单的函数,并将这些函数组合在一起,我们可以创建出更加强大和灵活的抽象。

首先,函数组合可以帮助我们减少代码的重复。在传统的面向对象设计中,我们常常需要创建大量的类和对象来实现特定的功能。然而,通过使用函数组合,我们可以将这些功能分解为一系列可复用的函数,从而减少代码的重复。

例如,假设我们正在编写一个处理图像的程序。我们可能需要实现一系列的操作,如旋转、缩放和裁剪等。在传统的设计中,我们可能会为每一种操作创建一个单独的类。然而,通过使用函数组合,我们可以将这些操作实现为一系列的函数,然后通过组合这些函数来创建更复杂的操作。

auto rotate = [](Image img, Angle angle) { /*...*/ };
auto scale = [](Image img, double factor) { /*...*/ };
auto crop = [](Image img, Rectangle rect) { /*...*/ };

auto processImage = compose(crop, compose(scale, rotate));

在这个例子中,processImage函数就是rotatescalecrop这三个函数的组合。这样,我们就可以在不改变这三个函数的情况下,灵活地改变它们的组合方式,从而实现不同的功能。

其次,函数组合可以提高代码的可读性。通过将复杂的操作分解为一系列简单的函数,我们可以使代码更容易理解。每个函数都有一个明确的目的,这使得代码的阅读者可以更容易地理解代码的功能。

最后,函数组合可以提高代码的可维护性。由于函数组合的代码更加模块化,因此更容易进行修改和测试。每个函数都可以独立地进行测试和修改,而不会影响到其他的函数。

总的来说,函数组合是一种强大的工具,它可以帮助我们创建出更加简洁、可读和可维护的代码。在现代的C++编程中,我们应该尽可能地利用函数组合来改进我们的软件设计。

3.3 函数组合在现代C++编程中的角色 (The Role of Function Composition in Modern C++ Programming)

在现代C++编程中,函数组合扮演着重要的角色。随着C++11、C++14、C++17和C++20等新标准的引入,C++的函数式编程能力得到了显著的提升,函数组合作为函数式编程的核心概念,其在C++编程中的应用也越来越广泛。

  1. 提升代码质量:函数组合可以帮助我们编写出更加简洁、可读和可维护的代码。通过将复杂的操作分解为一系列简单的函数,并将这些函数组合在一起,我们可以创建出更加强大和灵活的抽象。这不仅可以提升代码的质量,也可以提高开发效率。

  2. 强化抽象能力:函数组合可以强化我们的抽象能力。在面向对象编程中,我们通过创建类和对象来进行抽象。而在函数式编程中,我们则可以通过创建和组合函数来进行抽象。这种基于函数的抽象方式,可以提供一种全新的视角,帮助我们更好地理解和解决问题。

  3. 支持函数式编程范式:函数组合是支持函数式编程范式的重要工具。通过使用函数组合,我们可以更好地利用C++的函数式编程特性,如Lambda表达式、std::function、智能指针等。这可以帮助我们编写出更加高效、安全和优雅的代码。

  4. 促进代码复用:函数组合可以促进代码的复用。通过将通用的操作实现为函数,我们可以在多个地方复用这些函数。而通过函数组合,我们则可以灵活地组合这些函数,以实现更复杂的功能。

总的来说,函数组合在现代C++编程中扮演着重要的角色。随着C++对函数式编程支持的不断增强,我们有理由相信,函数组合将在未来的C++编程中发挥更大的作用。

4. 结语

4.1 函数组合的优点与限制 (Advantages and Limitations of Function Composition)

函数组合(Function Composition)是函数式编程(Functional Programming)的核心概念之一,它在C++中的实现,尤其是通过std::function的实现,为我们的编程实践带来了许多优点,但同时也存在一些限制。

优点 (Advantages)

  1. 代码简洁性(Code Conciseness):函数组合允许我们将多个函数链接在一起,形成一个新的函数。这种方式可以减少冗余的代码,使我们的代码更加简洁,更易于阅读和理解。

  2. 代码复用性(Code Reusability):通过函数组合,我们可以将一些常用的函数组合成一个新的函数,这样就可以在多个地方重复使用这个新的函数,而不需要重复编写相同的代码。

  3. 代码的可测试性(Code Testability):函数组合的每一个组成部分都是独立的函数,这意味着我们可以单独测试每一个函数,而不需要在一个复杂的环境中进行测试。

  4. 代码的可维护性(Code Maintainability):由于函数组合的每一个组成部分都是独立的函数,因此在需要修改代码时,我们只需要关注与修改相关的那部分函数,而不需要关注整个函数组合。

限制 (Limitations)

  1. 类型兼容性(Type Compatibility):在C++中,函数组合需要保证每一个函数的输出类型与下一个函数的输入类型相匹配。这就需要我们在编写函数时,必须非常注意函数的输入输出类型,否则可能会导致类型错误。

  2. 错误处理(Error Handling):在函数组合中,如果某个函数出现错误,那么这个错误会直接传递到整个函数组合中。这就需要我们在编写函数时,必须非常注意错误处理,否则可能会导致整个函数组合出现错误。

  3. 性能问题(Performance Issues):虽然函数组合可以使我们的代码更加简洁,但是如果我们不注意性能问题,可能会导致我们的代码运行效率降低。例如,如果我们在函数组合中使用了大量的临时对象,那么可能会导致内存使用过高,甚至可能导致程序崩溃。


下面是一个关于函数组合优点与限制的图示:
在这里插入图片描述

如图所示,函数组合的优点包括代码简洁性、代码复用性、代码的可测试性和代码的可维护性。而其限制则包括类型兼容性、错误处理和性能问题。这些优点和限制都是我们在使用函数组合时需要考虑的因素。

4.2 对函数式编程的思考 (Reflections on Functional Programming)

函数式编程(Functional Programming)是一种编程范式,它强调程序的执行结果而不是程序的执行过程,更注重表达式的求值而不是变量的赋值。在C++中,虽然它是一种多范式的编程语言,但是我们仍然可以利用其强大的特性,如std::function、lambda表达式等,来实现函数式编程的思想。

函数式编程的核心思想是使用函数来抽象数据操作,而不是使用循环和条件语句。这种方式可以使我们的代码更加简洁,更易于理解和维护。同时,由于函数式编程强调不可变性和无副作用,因此它可以帮助我们编写出更加安全、更容易测试的代码。

然而,函数式编程并不是万能的。在某些情况下,过度的函数抽象可能会导致代码的可读性和性能下降。此外,函数式编程的一些概念,如高阶函数、纯函数等,对于初学者来说可能有一定的学习难度。

总的来说,函数式编程是一种强大的编程范式,它可以帮助我们编写出更加简洁、更易于维护的代码。但是,我们在使用时也需要注意其潜在的问题,如代码的可读性和性能问题。因此,我们需要根据实际情况,灵活地运用函数式编程的思想,以达到编程的最优效果。

4.3 对未来C++发展的展望 (Outlook for the Future Development of C++)

C++作为一种多范式的编程语言,其强大的功能和灵活性使其在各种领域都有广泛的应用,包括系统软件、游戏开发、嵌入式系统、高性能计算等。随着C++标准的不断发展,C++已经引入了许多函数式编程的特性,如lambda表达式、std::function、std::bind等,这些特性使得我们可以在C++中更好地实现函数式编程的思想。

未来,我们期待C++能够在函数式编程方面做得更好。例如,我们期待C++能够引入更多的函数式编程特性,如更强大的lambda表达式、更灵活的函数组合机制等。同时,我们也期待C++能够在性能和易用性方面做出更多的改进,使得我们可以更方便、更高效地编写代码。

此外,我们也期待C++社区能够提供更多的教育和培训资源,帮助开发者更好地理解和使用函数式编程。通过这些努力,我们相信C++将会成为一个更强大、更易用的编程语言,能够更好地满足我们的编程需求。

总的来说,我们对C++的未来充满了期待。我们相信,随着C++标准的不断发展,C++将会成为一个更强大、更易用的编程语言,能够更好地满足我们的编程需求。

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

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

相关文章

【网络协议详解】——万维网WWW系统协议(学习笔记)

目录 &#x1f552; 1. 概述&#x1f552; 2. 文本传输协议HTTP&#x1f552; 3. HTTP的报文格式&#x1f552; 4. Cookie&#x1f552; 5. 万维网缓冲与代理服务器 &#x1f552; 1. 概述 万维网www&#xff08;World Wide Web&#xff09;并非某种特殊的计算机网络。它是一个…

两个iframe同时滚动实现界面内容对比功能

背景&#xff1a;因为要实现一个版本对比功能&#xff0c;所以要保证两个界面能同时滚动。&#xff08;本文只讲同时滚动&#xff0c;对比功能文本只讲思路&#xff0c;具体代码实现如有需要 可以联系我&#xff09;&#xff0c;因为过程中有部分收获特此记录。 本文参考&…

Jetson硬件 升级jetpack系统 版本流程

前言&#xff1a; 准备一个linux系统电脑&#xff0c;一个跳线帽&#xff0c;以及一条usb线 以及英伟达开发者账号&#xff0c;点击https://developer.nvidia.com/zh-cn/embedded/jetpack进行注册 注意&#xff1a;烧录的目标硬件是以前装过低版本的jetpack&#xff0c;以下步…

工业自动化新引擎:工业机器人引领制造业转型升级

自2010年开始&#xff0c;我国15-64岁人口比例下滑&#xff0c;截至2022年我国总人数出现负增长&#xff0c;同比下滑0.1%&#xff0c;因人口老龄化加剧和出生率的持续走低&#xff0c;致使进入生产体系的劳动力越来越少。 随着我国经济进入新常态&#xff0c;制造业面临着产能…

通过训练NLP制作一个自己的简易输入法

最近开始研究NLP&#xff0c;然后根据手写CV UP主的视频&#xff0c;写了一个N Gram的NLP模型&#xff0c;算是该领域里的hello world吧。然后我又添加了几行代码实现了一个非常简易的输入法。 项目说明&#xff1a; 数据集可以自创&#xff0c;导入txt文件即可&#xff1b; …

K8s in Action 阅读笔记——【6】Volumes: attaching disk storage to containers

K8s in Action 阅读笔记——【6】Volumes: attaching disk storage to containers 在前三章中&#xff0c;我们介绍了Pods以及它们与ReplicationControllers、ReplicaSets、DaemonSets、Jobs和Services等Kubernetes资源的交互。现在&#xff0c;我们将回到Pod内部&#xff0c;…

【java 基础一】 纯语法基础记录

一、基础 1.1 变量 Java 变量是程序中存储数据的容器。 在 Java 中&#xff0c;变量需要先声明再使用&#xff0c;并且必须先声明再赋值。 声明变量&#xff1a;声明变量时需要指定变量的类型、名称和初始值。例如&#xff0c;声明一个整型变量可以如下所示&#xff1a; in…

水处理施工方案合集

编制说明及工程简介 (一) 编制说明 本施工组织设计是依据建设单位提供的招标文件、施工图、同类工程施工资料和国家有关施工规范及验收标准进行编制的。本施工组织设计针对本工程施工中的关键点、难点及其处理措施&#xff0c;主要施工方法&#xff0c;施工组织部署&#xff…

如何理解 CRM 客户关系管理系统?

如何理解 CRM 客户关系管理系统&#xff1f; CRM的作用不止是工具&#xff0c;根据用户和对象的不同&#xff0c;CRM创造的价值也是不同的。 打个比方: 有的企业是用CRM来管理客户信息;有的企业是用CRM来获取流量的&#xff1b;有的企业是用CRM来做销售管理的&#xff1b;还…

Springboot整合OSS并实现文件上传和下载

目录 一.OSS服务器开通并创建账户 二.Springboot整合OSS 1.创建springboot项目 2.整合OSS 三.postman测试 一.OSS服务器开通并创建账户 参考阿里云OSS的使用(全程请登陆)_zhz小白的博客-CSDN博客https://blog.csdn.net/zhouhengzhe/article/details/112077301 二.Springb…

深度学习笔记之循环神经网络(八)LSTM的轻量级变体——门控循环单元(GRU)

深度学习笔记之LSTM轻量级变体——门控循环单元[GRU] 引言回顾&#xff1a; LSTM \text{LSTM} LSTM的前馈计算过程 LSTM \text{LSTM} LSTM的问题 GRU \text{GRU} GRU的前馈计算过程 GRU \text{GRU} GRU的优势 引言 上一节介绍了从反向传播过程的角度认识 LSTM \text{LSTM} LST…

【29】核心易中期刊推荐——计算语言学人工智能(AI)技术

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

使用javascript-obfuscator给js文件加密

一、安装javascript-obfuscator包 npm install javascript-obfuscator -g二、默认配置直接压缩文件 javascript-obfuscator miniprogram/src/utils/utils_create_sign.js --output miniprogram/src/utils/create_sign.js三、根据配置文件压缩文件 3.1、创建mixs.json配置文…

前端阿里云OSS直传,微信小程序版本

前言&#xff1a; 网络上许多的文章资料&#xff0c;全是使用阿里云官方的SDK&#xff0c;ali-oss插件去做直传。可是各位素未谋面的朋友要注意&#xff0c;这个SDK它支持web环境使用&#xff0c;也就是PC端浏览器。 当项目环境切换到微信小程序&#xff0c;是无法使用这种方…

Power BI Embedded自动缩放容量,为公司每个月节省上万元

哎&#xff0c;不知道今年行情怎么就这样了&#xff0c;大厂一边大批毕业生&#xff0c;一边大量招人。难道是今年的新人便宜&#xff1f;就连道哥&#xff08;吴翰清&#xff0c;阿里P10&#xff0c;中国顶级黑客&#xff09;都从阿里离职了&#xff0c;当年年少不懂学计算机&…

Nodejs批量处理图片小工具:批量修改图片信息

小工具一&#xff1a;批量修改文件夹里面的图片名称 步骤&#xff1a; 1.安装nodejs。 2.根据需要修改editFileName(filePath, formatName)函数的参数&#xff0c;也可以不改&#xff0c;直接将renameFile.js和img文件夹放在同一个目录下。 3.在renameFile.js目录下开启终端…

SQL报错this is incompatible with sql_mode=only_full_group_by

一、bug记录 1.1.bug截图 1.2.sql语句 SELECT id,batch_no,if_code,channel_mch_no,bill_date,bill_type,currency,order_id, channel_order_no,channel_amount,channel_fee_amount,channel_success_at, channel_user,channel_state,org_pay_order_id,channel_refund_amoun…

曾经由盛转衰的骈文,却引领后人在文质兼美的创作之路上坚定前行

又叫骈体文&#xff0c;是和散文相对应的一种文体&#xff0c;它兴起于汉末&#xff0c;形成于魏晋&#xff0c;最盛行于南北朝&#xff0c;在初唐、中唐、唐末、五代、宋初时也盛极一时。古人语&#xff1a;两马并驾为骈&#xff0c;所以骈文最大的特点是用对偶的手法&#xf…

Fiddler抓包工具之fiddler设置手机端抓包

fiddler设置手机端抓包 安卓手机抓包 第一步&#xff1a;配置电脑和安卓的相关设置 1、手机和fiddler位于同一个局域网内&#xff1b;首先从fiddler处获取到ip地址和端口号&#xff1a; &#xff0c;点击online&#xff0c;最后一行就是ip地址 2、路径&#xff1a;Tools》O…

数据库基础——10.子查询

这篇文章来讲一下数据库的子查询 目录 1. 需求分析与问题解决 1.1 实际问题 1.2 子查询的基本使用 1.3 子查询的分类 2. 单行子查询 2.1 单行比较操作符 2.2 代码示例 2.3 HAVING 中的子查询 2.4 CASE中的子查询 2.5 子查询中的空值问题 2.5 非法使用子查询​编辑…