(七)[重制]C++命名空间与标准模板库(STL)

引言

在专栏C++教程的第六篇C++中的结构体与联合体中,介绍了C++中的结构体和联合体,包括它们的定义、初始化、内存布局和对齐,以及作为函数参数和返回值的应用。在专栏C++教程的第七篇中,我们将深入了解C++中的命名空间(namespace)和标准模板库(STL)的相关概念和应用

C++ 命名空间(namespace)

C++ 命名空间在软件开发中起着至关重要的作用,特别是在大型项目中。命名空间的主要作用是解决全局名称冲突的问题。在大型项目中,不同模块可能定义了相同名称的函数、变量或类。通过将这些实体分别放入不同的命名空间内,可以在全局范围内区分它们。接下来,我们将详细介绍命名空间的相关内容,并通过生动有趣的示例来帮助理解。

1. 命名空间的作用

想象一下你正在开发一个复杂的应用程序,其中包括多个模块,如账户管理、交易处理、报告生成等。每个模块都有自己的一组函数和类,例如,Account 类在账户管理模块中用于表示用户账户,而在交易处理模块中,可能也有一个 Transaction 类表示金融交易。如果不使用命名空间,这些类名可能会发生冲突,从而导致编译错误或意外行为。

为了避免这种情况,我们可以将每个模块的代码放入不同的命名空间中:

namespace AccountManagement {
    class Account {
        // 账户管理相关代码
    };
}

namespace TransactionProcessing {
    class Transaction {
        // 交易处理相关代码
    };
}

通过这种方式,即使两个模块中都有同名的类,它们也不会冲突。我们可以通过命名空间限定符来区分它们:

AccountManagement::Account myAccount;
TransactionProcessing::Transaction myTransaction;

2. 命名空间成员访问方式

在使用命名空间时,我们有多种方式访问其中的成员。

显式作用域解析运算符

最直接的方式是使用作用域解析运算符 :: 来显式指定命名空间:

namespace MyNamespace {
    void function() {
        // 函数实现
    }
}

int main() {
    MyNamespace::function(); // 显式调用命名空间内的函数
    return 0;
}

using 声明

我们也可以使用 using 声明将特定的命名空间成员导入到当前作用域,这样就可以直接使用这些成员而无需每次都写命名空间前缀:

namespace MyNamespace {
    void function() {
        // 函数实现
    }
}

using MyNamespace::function; // 导入特定函数到当前作用域

int main() {
    function(); // 现在可以直接调用
    return 0;
}

using 指令

using namespace 语句用于导入整个命名空间的内容到当前作用域。尽管方便,但在头文件中使用可能会导致污染全局命名空间,增加编译错误和维护难度。因此,一般建议仅在实现文件中使用 using namespace,而在头文件中尽量避免。

namespace MyNamespace {
    void function() {
        // 函数实现
    }
}

// 在 cpp 文件中使用
using namespace MyNamespace;

int main() {
    function(); // 直接调用
    return 0;
}

3. 内联命名空间

C++11 引入了内联命名空间(inline namespace),它的主要特点是链接时不会创建新的作用域,而是保留原作用域。内联命名空间主要用于版本控制和 ABI 兼容性问题。

假设你在开发一个库,并希望在新版本中添加一些功能,但不希望破坏与旧版本的兼容性。你可以使用内联命名空间来实现这一点:

namespace MyLibrary {
    inline namespace v1 {
        void function() {
            // 旧版本实现
        }
    }

    inline namespace v2 {
        void function() {
            // 新版本实现
        }
    }
}

int main() {
    MyLibrary::function(); // 调用新版本的实现
    return 0;
}

通过这种方式,用户可以选择性地使用旧版本或新版本的实现,而无需修改代码。

4. 匿名命名空间

匿名命名空间中的所有内容具有内部链接属性,意味着它们只在同一编译单元可见,这有助于实现文件私有数据。匿名命名空间常用于定义只在当前文件中使用的辅助函数或变量,避免它们在全局范围内被意外使用。

namespace {
    void helperFunction() {
        // 辅助函数实现
    }
}

int main() {
    helperFunction(); // 调用匿名命名空间内的辅助函数
    return 0;
}

使用匿名命名空间可以有效地避免命名冲突,并确保辅助函数或变量只在当前文件中可见。

C++ 标准模板库(STL)详解

C++ 标准模板库(STL)是 C++ 标准库的一部分,提供了一组常用的数据结构和算法。STL 的设计原则是泛型编程,通过模板实现通用的容器和算法,使代码更加灵活和可重用。接下来,我们将详细介绍 STL 的各个方面,并通过生动有趣的示例来帮助理解。

1. STL 容器

STL 容器是 STL 的核心组件之一,每个容器都有其独特的特性和适用场景。以下是常用 STL 容器的介绍及示例。

std::vector

std::vector 是一种动态数组,支持高效的随机访问。它的插入和删除操作可能会导致元素移动,因此在需要频繁插入和删除的场景中性能不如链表。

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 访问元素
    std::cout << "Element at index 2: " << vec[2] << std::endl;

    // 插入元素
    vec.push_back(6);
    std::cout << "Last element: " << vec.back() << std::endl;

    // 删除元素
    vec.pop_back();
    std::cout << "After pop_back, last element: " << vec.back() << std::endl;

    return 0;
}

std::deque

std::deque 是一种双端队列,支持在两端进行高效的插入和删除操作。它既可以用作栈,也可以用作队列。

#include <deque>
#include <iostream>

int main() {
    std::deque<int> deq = {1, 2, 3, 4, 5};

    // 访问元素
    std::cout << "Element at index 2: " << deq[2] << std::endl;

    // 在前端插入元素
    deq.push_front(0);
    std::cout << "First element: " << deq.front() << std::endl;

    // 在后端插入元素
    deq.push_back(6);
    std::cout << "Last element: " << deq.back() << std::endl;

    // 删除前端元素
    deq.pop_front();
    std::cout << "After pop_front, first element: " << deq.front() << std::endl;

    return 0;
}

std::list

std::list 是一种双向链表,支持高效的插入和删除操作,但不支持随机访问。它适用于需要频繁插入和删除元素的场景。

#include <list>
#include <iostream>

int main() {
    std::list<int> lst = {1, 2, 3, 4, 5};

    // 遍历元素
    for (int elem : lst) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 插入元素
    auto it = lst.begin();
    std::advance(it, 2);
    lst.insert(it, 10);

    // 删除元素
    lst.erase(it);

    // 遍历元素
    for (int elem : lst) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

std::set 和 std::map

std::setstd::map 是基于红黑树实现的有序容器,键唯一,自动排序。std::set 仅包含键,而 std::map 包含键值对。

#include <set>
#include <map>
#include <iostream>

int main() {
    // std::set 示例
    std::set<int> mySet = {5, 3, 8, 1};
    mySet.insert(4);
    for (int elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // std::map 示例
    std::map<int, std::string> myMap;
    myMap[1] = "one";
    myMap[2] = "two";
    myMap[3] = "three";

    for (const auto& pair : myMap) {
        std::cout << pair.first <<

 " => " << pair.second << std::endl;
    }

    return 0;
}

std::multiset 和 std::multimap

std::multisetstd::multimap 允许键重复,其他特性与 std::setstd::map 相同。

#include <set>
#include <map>
#include <iostream>

int main() {
    // std::multiset 示例
    std::multiset<int> myMultiSet = {5, 3, 8, 1, 3, 5};
    for (int elem : myMultiSet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // std::multimap 示例
    std::multimap<int, std::string> myMultiMap;
    myMultiMap.insert({1, "one"});
    myMultiMap.insert({2, "two"});
    myMultiMap.insert({1, "uno"});

    for (const auto& pair : myMultiMap) {
        std::cout << pair.first << " => " << pair.second << std::endl;
    }

    return 0;
}

适配器容器

适配器容器是对其他容器的封装,提供特定的接口,例如栈(stack)、队列(queue)和优先级队列(priority_queue)。

#include <stack>
#include <queue>
#include <iostream>

int main() {
    // 栈示例
    std::stack<int> myStack;
    myStack.push(1);
    myStack.push(2);
    myStack.push(3);

    while (!myStack.empty()) {
        std::cout << myStack.top() << " ";
        myStack.pop();
    }
    std::cout << std::endl;

    // 队列示例
    std::queue<int> myQueue;
    myQueue.push(1);
    myQueue.push(2);
    myQueue.push(3);

    while (!myQueue.empty()) {
        std::cout << myQueue.front() << " ";
        myQueue.pop();
    }
    std::cout << std::endl;

    // 优先级队列示例
    std::priority_queue<int> myPriorityQueue;
    myPriorityQueue.push(3);
    myPriorityQueue.push(1);
    myPriorityQueue.push(2);

    while (!myPriorityQueue.empty()) {
        std::cout << myPriorityQueue.top() << " ";
        myPriorityQueue.pop();
    }
    std::cout << std::endl;

    return 0;
}

2. STL 算法

STL 提供了丰富的算法库,包括非修改序列算法、修改序列算法、排序算法、数值算法等。这些算法通常与迭代器配合使用。

非修改序列算法

非修改序列算法不会改变容器的内容,它们通常用于查找、统计和检查元素。

#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 3};

    // 查找元素
    auto it = std::find(vec.begin(), vec.end(), 3);
    if (it != vec.end()) {
        std::cout << "Found 3 at index " << std::distance(vec.begin(), it) << std::endl;
    } else {
        std::cout << "3 not found" << std::endl;
    }

    // 统计元素个数
    int count = std::count(vec.begin(), vec.end(), 3);
    std::cout << "Number of 3s: " << count << std::endl;

    // 检查是否所有元素都大于 0
    bool allPositive = std::all_of(vec.begin(), vec.end(), [](int x) { return x > 0; });
    std::cout << "All elements are positive: " << (allPositive ? "true" : "false") << std::endl;

    return 0;
}

修改序列算法

修改序列算法会改变容器的内容,它们包括排序、复制、替换等操作。

#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> vec = {4, 2, 5, 1, 3};

    // 排序
    std::sort(vec.begin(), vec.end());
    std::cout << "Sorted vector: ";
    for (int elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 反转
    std::reverse(vec.begin(), vec.end());
    std::cout << "Reversed vector: ";
    for (int elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 复制
    std::vector<int> vec2(vec.size());
    std::copy(vec.begin(), vec.end(), vec2.begin());
    std::cout << "Copied vector: ";
    for (int elem : vec2) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

排序算法

STL 提供了一些高级排序算法,例如 std::sortstd::stable_sort

#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> vec = {4, 2, 5, 1, 3};

    // 使用 std::sort 排序
    std::sort(vec.begin(), vec.end());
    std::cout << "Sorted vector: ";
    for (int elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 使用 std::stable_sort 排序,保留相等元素的相对顺序
    std::stable_sort(vec.begin(), vec.end());
    std::cout << "Stable sorted vector: ";
    for (int elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

数值算法

STL 还提供了一些数值算法,如 std::accumulate 用于求和,std::partial_sumstd::adjacent_difference 用于累积和差分。

#include <vector>
#include <numeric>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 求和
    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    std::cout << "Sum: " << sum << std::endl;

    // 部分和
    std::vector<int> partialSums(vec.size());
    std::partial_sum(vec.begin(), vec.end(), partialSums.begin());
    std::cout << "Partial sums: ";
    for (int elem : partialSums) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 相邻差分
    std::vector<int> differences(vec.size());
    std::adjacent_difference(vec.begin(), vec.end(), differences.begin());
    std::cout << "Adjacent differences: ";
    for (int elem : differences) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

3. STL 迭代器

迭代器是 STL 的核心概念之一,它提供了访问容器内元素的一致接口。STL 迭代器类似于指针,但具有更多的功能。根据迭代器的能力,它们分为以下几种类型:

输入迭代器

输入迭代器只能读取元素并单向前进,适用于单次遍历序列的操作。

#include <vector>
#include <iostream>
#include <iterator>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用输入迭代器遍历向量
    for (std::istream_iterator<int> it(std::cin), end; it != end; ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出迭代器

输出迭代器只能写入元素并单向前进,适用于将结果输出到序列的操作。

#include <vector>
#include <iostream>
#include <iterator>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用输出迭代器将向量元素输出到标准输出
    std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

前向迭代器

前向迭代器除了输入迭代器的功能外,还可以前进后再次前进,适用于多次遍历序列的操作。

#include <vector>
#include <iostream>
#include <iterator>

int main() {
    std::vector<int> vec = {1, 2,

 3, 4, 5};

    // 使用前向迭代器遍历向量
    for (std::forward_list<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

双向迭代器

双向迭代器不仅可以前进,还可以后退,适用于需要双向遍历序列的操作。

#include <list>
#include <iostream>

int main() {
    std::list<int> myList = {1, 2, 3, 4, 5};

    // 使用双向迭代器遍历列表
    for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 反向遍历列表
    for (std::list<int>::reverse_iterator it = myList.rbegin(); it != myList.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

随机访问迭代器

随机访问迭代器可以直接跳转到任意位置,适用于数组和向量等支持随机访问的容器。

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用随机访问迭代器访问向量元素
    for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 直接跳转到任意位置
    std::vector<int>::iterator it = vec.begin() + 2;
    std::cout << "Element at index 2: " << *it << std::endl;

    return 0;
}

4. STL 函数对象和谓词

STL 中的函数对象和谓词提供了灵活的函数调用方式。函数对象是行为类似函数的对象,谓词是返回布尔值的函数对象。

函数对象

函数对象是重载了 operator() 的类对象,可以像函数一样被调用。

#include <vector>
#include <algorithm>
#include <iostream>

class MultiplyBy {
public:
    MultiplyBy(int factor) : factor(factor) {}
    int operator()(int x) const {
        return x * factor;
    }
private:
    int factor;
};

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::vector<int> result(vec.size());

    // 使用函数对象进行元素变换
    std::transform(vec.begin(), vec.end(), result.begin(), MultiplyBy(2));

    std::cout << "Transformed vector: ";
    for (int elem : result) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

谓词

谓词是返回布尔值的函数对象,分为一元谓词和二元谓词。

#include <vector>
#include <algorithm>
#include <iostream>

class IsEven {
public:
    bool operator()(int x) const {
        return x % 2 == 0;
    }
};

class IsGreater {
public:
    IsGreater(int value) : value(value) {}
    bool operator()(int x) const {
        return x > value;
    }
private:
    int value;
};

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6};

    // 使用一元谓词
    auto it = std::find_if(vec.begin(), vec.end(), IsEven());
    if (it != vec.end()) {
        std::cout << "First even number: " << *it << std::endl;
    } else {
        std::cout << "No even numbers found" << std::endl;
    }

    // 使用二元谓词
    it = std::find_if(vec.begin(), vec.end(), IsGreater(4));
    if (it != vec.end()) {
        std::cout << "First number greater than 4: " << *it << std::endl;
    } else {
        std::cout << "No numbers greater than 4 found" << std::endl;
    }

    return 0;
}

绑定器和函数适配器

STL 提供了绑定器和函数适配器,用于调整函数对象和谓词的行为。

#include <vector>
#include <algorithm>
#include <iostream>
#include <functional>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6};

    // 使用 std::bind
    auto it = std::find_if(vec.begin(), vec.end(), std::bind(std::greater<int>(), std::placeholders::_1, 4));
    if (it != vec.end()) {
        std::cout << "First number greater than 4: " << *it << std::endl;
    } else {
        std::cout << "No numbers greater than 4 found" << std::endl;
    }

    return 0;
}

总结

本文详细探讨了C++中命名空间和标准模板库(STL)的重要概念及其实际应用:

在命名空间部分,我们学习了命名空间的基本作用,即解决全局名称冲突的问题,通过显式作用域解析运算符和using声明的方式来访问命名空间中的成员。讨论了使用using namespace带来的便利性和潜在的命名冲突问题,以及C++11引入的内联命名空间和匿名命名空间的用法和优势。

在STL部分,我们深入研究了各种STL容器的特性和适用场景,如动态数组vector、双端队列deque、双向链表list,以及基于红黑树的关联容器set和map。我们介绍了STL提供的丰富算法库,包括查找、排序、复制等非修改序列算法和修改序列算法,以及迭代器的不同类型和功能,如输入迭代器、输出迭代器和随机访问迭代器。

Tip:为了获得更深入的学习体验,请参考相关教程或书籍,了解C++语言的更多基本结构和基本语法。

在这里插入图片描述
每篇图片分享
图片来自inscode上的开源程序
濒危动物:马来熊

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

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

相关文章

C++(Qt)-GIS开发-简易瓦片地图下载器

Qt-GIS开发-简易瓦片地图下载器 文章目录 Qt-GIS开发-简易瓦片地图下载器1、概述2、安装openssl3、实现效果4、主要代码4.1 算法函数4.2 瓦片地图下载url拼接4.3 多线程下载 5、源码地址6、参考 更多精彩内容&#x1f449;个人内容分类汇总 &#x1f448;&#x1f449;GIS开发 …

连锁门店如何快速联网

随着新零售业态的发展&#xff0c;连锁门店的运营模式逐渐转为数字化运营&#xff0c;新增了诸如收银PoS、扫码枪、摄像头等数字化终端。这些数字化的业务应用都需要依托稳定可靠的网络才能正常运转&#xff0c;在这样的背景下&#xff0c;连锁门店对网络连接的需求显得尤为关键…

C++下Protobuf学习

C下Protobuf简单学习 Protobuf&#xff08;Protocol Buffers&#xff09;协议是一种由 Google 开发的高效的、跨语言的、平台无关的数据序列化协议&#xff0c;提供二进制序列化格式和相关的技术&#xff0c;它用于高效地序列化和反序列化结构化数据&#xff0c;通常用于网络通…

WordPress网站违法关键词字过滤插件下载text-filter

插件下载地址&#xff1a;https://www.wpadmin.cn/2025.html 插件介绍 WordPress网站违法关键词字过滤插件text-filter由本站原创开发,支持中英文关键字自动替换成**号&#xff0c;可以通过自定义保存修改按钮增加“预设关键字”&#xff0c;也可以导入定义好的txt文本形式的关…

single_test_funi.py: error: the following arguments are required: img

parser.add_argument(img, defaultS/1.jpg, helpImage file) 当你已经指定了文件路径&#xff0c;还是报错怎么办&#xff1f; parser.add_argument(img, nargs?, defaultS/1.jpg, helpImage file) nargs? 表示 config 参数是可选的。如果用户没有提供这个参数&#xff0c…

【ARMv8/v9 GIC 系列 5.6 -- GIC 超优先级中断详细介绍】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 Interrupt superpriority超优先级中断的特性和应用Physical interface interrupt signalsPhysical Group 1 Non-NMI for Current Security StatePhysical Group 1 for Other Security State, or a Group 0 Non-NMIPhysical Group 1 …

JVM原理(十八):JVM虚拟机的编译器优化技术

1. 编译器优化技术 编译器的目标虽然是做程序代码翻译为本地机器 码的工作&#xff0c;但其实难点并不在于能不能成功翻译出机器码&#xff0c;输出代码优化质量的高低才是决定编译器优秀与否的关键。 1.1. 优化技术概览 即时编译器对这些代码优化变换是建立在代码的中间表示…

基于Android Studio点餐项目,点餐app

目录 项目介绍 图片展示 运行环境 获取方式 项目介绍 实现登录、注册、注销功能&#xff0c;退出登录等功能&#xff0c; 以及基本的选择店铺点餐&#xff0c;加入购物车和结算等功能&#xff0c;以及可以增加或者减少商品的个数&#xff0c; 同时可以同步价格的总量。以…

两年经验前端带你重学前端框架必会的ajax+node.js+webpack+git等技术的个人学习心得、作业及bug记录 Day1

黑马程序员前端AJAX入门到实战全套教程&#xff0c;包含学前端框架必会的&#xff08;ajaxnode.jswebpackgit&#xff09;&#xff0c;一套全覆盖 Day1 你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​…

沙龙回顾|MongoDB如何充当企业开发加速器?

数据不仅是企业发展转型的驱动力&#xff0c;也是开发者最棘手的问题。前日&#xff0c;MongoDB携手阿里云、NineData在杭州成功举办了“数据驱动&#xff0c;敏捷前行——MongoDB企业开发加速器”技术沙龙。此次活动吸引了来自各行各业的专业人员&#xff0c;共同探讨MongoDB的…

大话C语言:第27篇 内存模型

1 存储硬件概述 现代计算机遵循冯诺依曼体系结果&#xff0c;存储分为&#xff1a; 外部存储器&#xff1a;长期存放数据&#xff0c;掉电不丢失数据。例如&#xff0c;硬盘、flash、rom、u 盘、光盘、磁带。 内部存储器&#xff1a;暂时存放数据&#xff0c;掉电数据丢失。例…

小白学python(第六天)循环之异变

本篇文章给大家讲解的是循环语句&#xff0c;那么闲话少叙&#xff0c;我们进入正题 在c、Java中循环都是三剑客&#xff0c;那么大家可还记得是哪三位剑客吗 剑客一&#xff1a;while循环 剑客二&#xff1a;for循环 剑客三&#xff1a;do{……}while&#xff08;&…

springcloud-alibba之FeignClient

代码地址&#xff1a;springcloud系列: springcloud 组件分析拆解 1.FeignClient的集成 springboot版本&#xff1a;3.1.5 springcloud组件版本&#xff1a;2022.0.4 nacos客户端的版本&#xff1a;2.3.2 1.引pom 这里引入了nacos和feginclient的版本 <dependency>…

MongoDB 单节点升级为副本集高可用集群(1主1从1仲裁)

作者介绍&#xff1a;老苏&#xff0c;10余年DBA工作运维经验&#xff0c;擅长Oracle、MySQL、PG、Mongodb数据库运维&#xff08;如安装迁移&#xff0c;性能优化、故障应急处理等&#xff09; 公众号&#xff1a;老苏畅谈运维 欢迎关注本人公众号&#xff0c;更多精彩与您分享…

SpringBoot 实现视频分段播放(通过进度条来加载视频)

需求&#xff1a;现在我本地电脑中有一个文件夹&#xff0c;文件夹中都是视频&#xff0c;需要实现视频播放的功能。 问题&#xff1a;如果通过类似 SpringBoot static 文件夹的方式来实现&#xff0c;客户端要下载好完整的视频之后才可以播放&#xff0c;并且服务端也会占用大…

计算机网络之以太网

上文内容&#xff1a;总线局域网以及冲突的解决方法 1.以太网的起源 1.1起源 60年代末期&#xff0c;夏威夷大学Norman Abramson等研制ALOHA无线网络系统,实现Oahu岛上的主机和其它岛及船上的读卡机和终端通信&#xff1b; 出境信道地址&#xff1a;主机到终端&#xff1…

vue3 + 百度地图 实现多坐标生成轨迹的两种种方式

本次依然是关于百度地图中常见的一个问题&#xff0c;此次共使用了两种方式并做了一些分析及处理&#xff0c;希望有所帮助。如有问题可以评论或私信。 一、便捷方式 优点&#xff1a;便捷&#xff0c;所用的api方法是根据坐标进行计算后绘制路线&#xff0c;所以路线相对准确…

制定事件响应计划的四个关键步骤,如何做到风险闭环

一个有效的安全事件响应策略的关键组成部分有哪些&#xff1f;一个有效的安全事件响应策略包括四个关键组成部分&#xff0c;它们协同工作以确保对网络安全问题的快速和有效响应。 一个有效的安全事件响应策略的关键组成部分有哪些&#xff1f; 一个有效的安全事件响应策略包括…

Java常用算法集合扩容机制分析

基础篇 基础篇要点&#xff1a;算法、数据结构、基础设计模式 1. 二分查找 要求 能够用自己语言描述二分查找算法能够手写二分查找代码能够解答一些变化后的考法 算法描述 前提&#xff1a;有已排序数组 A&#xff08;假设已经做好&#xff09; 定义左边界 L、右边界 R&…

SQLite 命令行客户端 + Windows 批处理应用

SQLite 命令行客户端 Windows 批处理应用 下载 SQLite 客户端1. Bat 辅助脚本1. 执行SQL.bat执行 2. 导出Excel.bat执行效果 3. 导出HTML.bat执行效果 4. 清空-订单表.bat 2. 测试 SQL1. 创建订单表.sql2. 插入订单表.sql3. 查询订单表.sql4. 清空订单表.sql5. 删除订单表.sql…