【C++】迭代器

2023-11-15

目录

1. 迭代器

1.1 迭代器的操作

1.2 迭代器范围

1.3 使用左闭合范围蕴含的编程假定

2. begin和end成员

3. 容器操作可能使迭代器失效

3.1 迭代器失效

3.2 编写改变容器的循环程序

3.3 不要保存end返回的迭代器

4. 反向迭代器

4.1 反向迭代器的概念

4.2 反向迭代器需要递减运算符

4.3 反向迭代器和其他迭代器间的关系


1. 迭代器

1.1 迭代器的操作

与容器一样,迭代器有着公共的接口:如果一个迭代器提供某个操作,那么所有提供相同操作的迭代器对这个操作的实现方式都是相同的。例如,标准容器类型上的所有迭代器都允许我们访问容器中的元素,而所有迭代器都是通过解引用运算符来实现这个操作的。类似的,标准库容器的所有迭代器都定义了递增运算符,从当前元素移动到下一个元素。

表1列出了容器迭代器支持的所有操作,其中有一个例外不符合公共接口特点——forward_list迭代器不支持递减运算符(--)。

表1 迭代器的运算符
*iter 返回迭代器iter所指元素的引用
iter->mem 解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter 令iter指示容器中的下一个元素
--iter 令iter指示容器中的上一个元素
iter1 == iter2 判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元素或者它们是同一个容器的尾后迭代器,则相等;反之,不相等。
iter1 != iter2

表2列出了迭代器支持的算术运算,这些运算只能应用于string、vector、deque和array的迭代器。我们不能将它们用于其他任何容器类型的迭代器。

表2 迭代器支持的运算
iter + n 迭代器加上一个整数值仍得一个迭代器,迭代器指示的新位置与原来相比向前移动了若干个元素。结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一位置。
iter - n 迭代器减去一个整数值仍得一个迭代器,迭代器指示的新位置与原来相比向后移动了若干个元素。结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一位置。
iter1 += n 迭代器加法的复合赋值语句,将iter1加n的结果赋给iter1
iter1 -= n 迭代器减法的复合赋值语句,将iter1减n的结果赋给iter1
iter1 - iter2 两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动差值个元素后将得到左侧的迭代器。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一位置。
>、>=、<、<= 迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之前,则说前者小于后者。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下一位置。

1.2 迭代器范围

迭代器范围的概念是标准库的基础。

一个迭代器范围(iterator range)由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者是尾元素之后的位置(one past the last element)。这两个迭代器通常被称为begin和end,或者是first和last(可能有些误导),它们标记了容器中元素的一个范围。

虽然第二个迭代器常常被称为last,但这种叫法有些误导,因为第二个迭代器从来都不会指向范围中的最后一个元素,而是指向尾元素之后的位置。迭代器范围中的元素包含first所表示的元素以及从first开始直至last(但不包含last)之间的所有元素。

这种元素范围被称为左闭合区间(left-inclusive interval),其标准数学描述为[begin, end)。

表示范围自begin开始,于end之前结束。迭代器begin和end必须指向相同的容器。end可以与begin指向相同的位置,但不能指向begin之前的位置。

如果满足如下条件,两个迭代器begin和end构成一个迭代器范围:

  • 它们指向同一个容器中的元素,或者是容器最后一个元素之后的位置。
  • 我们可以通过反复递增begin来到达end。换句话说,end不在begin之前。

编译器不会强制这些要求。确保程序符合这些约定是程序员的责任。

1.3 使用左闭合范围蕴含的编程假定

标准库使用左闭合范围是因为这种范围有三种方便的性质。假定begin和end构成一个合法的迭代器范围,则

  • 如果begin与end相等,则范围为空
  • 如果begin与end不等,则范围至少包含一个元素,且begin指向该范围中的第一个元素
  • 我们可以对begin递增若干次,使得begin==end

这些性质意味着我们可以像下面的代码一样用一个循环来处理一个元素范围,而这是安全的:

while (begin != end)
{
    *begin = val; // ok 范围非空,因此begin指向一个元素
    ++begin;      // 移动迭代器,获取下一个元素
}

给定构成一个合法范围的迭代器begin和end,若begin==end,则范围为空。在此情况下,我们应该退出循环。如果范围不为空,begin指向此非空范围的一个元素。因此,在while循环体中,可以安全地解引用begin,因为begin必然指向一个元素。最后,由于每次循环对begin递增一次,我们确定循环最终会结束。

2. begin和end成员

begin和end操作生成指向容器中第一个元素和尾元素之后位置的迭代器。这两个迭代器最常见的用途是形成一个包含容器中所有元素的迭代器范围。

表3 获取迭代器操作
begin end
rbegin rend
cbegin cend
crbegin crend

如表3所示,begin和end有多个版本:带r的版本返回反向迭代器;以c开头的版本则返回const迭代器:

list<string> a = { "Milton","Shakespeare","Austen" };
auto it1 = a.begin();   // list<string>::iterator
auto it2 = a.rbegin();  // list<string>::reverse_iterator
auto it3 = a.cbegin();  // list<string>::const_iterator
auto it4 = a.crbegin(); // list<string>::const_reverse_iterator

不以c开头的函数都是被重载过的。也就是说,实际上有两个名为begin的成员。一个是const成员,返回容器的const_iterator类型。另一个是非常量成员,返回容器的iterator类型。rbegin、end和rend的情况类似。当我们对一个非常量对象调用这些成员时,得到的是返回iterator的版本。只有在对一个const对象调用这些函数时,才会得到一个const版本。与const指针和引用类似,可以将一个普通的iterator转换为对应的const_iterator,但反之不行。

以c开头的版本是C++新标准引入的,用以支持auto与begin和end函数结合使用。过去,没有其他选择,只能显式声明希望使用哪种类型的迭代器:

// 显式指定类型
list<string>::iterator it5 = a.begin();
list<string>::const_iterator it6 = a.begin();

// 是iterator还是const_iterator依赖于a的类型
auto it7 = a.begin();  // 仅当a是const时,it7是const_iterator
auto it8 = a.cbegin(); // it8是const_iterator

当auto与begin或end结合使用时,获得的迭代器类型依赖于容器类型,与我们想要如何使用迭代器毫不相干。但以c开头的版本还是可以获得const_iterator的,而不管容器的类型是什么。

当不需要写访问时,应使用cbegin和cend。

3. 容器操作可能使迭代器失效

3.1 迭代器失效

向容器中添加元素和从容器中删除元素的操作可能会使指向容器元素的指针、引用或迭代器失效。一个失效的指针、引用或迭代器将不再表示任何元素。使用失效的指针、引用或迭代器是一种严重的程序设计错误,很可能引起与使用未初始化指针一样的问题。

在向容器添加元素后:

  • 如果容器是vector或string,且存储空间被重新分配,则指向容器的迭代器、指针和引用都会失效。如果存储空间未重新分配,指向插入位置之前的元素的迭代器、指针和引用仍有效,但指向插入位置之后元素的迭代器、指针和引用将会失效。
  • 对于deque,插入到除首尾位置之外的任何位置都会导致迭代器、指针和引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。
  • 对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用仍有效。

当我们从一个容器中删除元素后,指向被删除元素的迭代器、指针和引用会失效,这应该不会令人惊讶。毕竟,这些元素都已经被销毁了。当我们删除一个元素后:

  • 对于list和forward_list,指向容器其他位置的迭代器(包括尾后迭代器和首前迭代器)、引用和指针仍有效。
  • 对于deque,如果在首尾之外的任何位置删除元素,那么指向被删除元素外其他元素的迭代器、引用或指针也会失效。如果是删除deque的尾元素,则尾后迭代器也会失效,但其他迭代器、引用和指针不受影响;如果是删除首元素,这些也不会受影响。
  • 对于vector和string,指向被删元素之前元素的迭代器、引用和指针仍有效。注意:当我们删除元素时,尾后迭代器总是会失效。

使用失效的迭代器、指针或引用是严重的运行时错误。

建议:管理迭代器

当你使用迭代器(或指向容器元素的引用或指针)时,最小化要求迭代器必须保持有效的程序片段是一个好的方法。

由于向迭代器添加元素和从迭代器删除元素的代码可能会使迭代器失效,因此必须保证每次改变容器的操作之后都正确地重新定位迭代器。这个建议对vector、string和deque尤为重要。

3.2 编写改变容器的循环程序

添加/删除vector、string或deque元素的循环程序必须考虑迭代器、引用和指针可能失效的问题。程序必须保证每个循环步中都更新迭代器、引用或指针。如果循环中调用的是insert或erase,那么更新迭代器很容易。这些操作都返回迭代器,我们可以用来更新:

// 傻瓜循环,删除偶数元素,复制每个奇数元素
vector<int> vi = { 0,1,2,3,4,5,6,7,8,9 };
auto iter = vi.begin(); // 调用begin而不是cbegin,因为我们要改变vi
while (iter != vi.end())
{
	if (*iter % 2)
    {
		iter = vi.insert(iter, *iter); // 复制当前元素
		iter += 2; // 向前移动迭代器,跳过当前元素以及插入到它之前的元素
	}
    else
    {
		iter = vi.erase(iter); // 删除偶数元素
		// 不应向前移动迭代器,iter指向我们删除的元素之后的元素
    }
}

此程序删除vector中的偶数值元素,并复制每个奇数值元素。我们在调用insert和erase后都更新迭代器,因为两者都会使迭代器失效。

在调用erase后,不必递增迭代器,因为erase返回的迭代器已经指向序列中下一个元素。调用insert后,需要递增迭代器两次。记住,insert在给定位置之前插入新元素,然后返回指向新插入元素的迭代器。因此,在调用insert后,iter指向新插入元素,位于我们正在处理的元素之前。我们将迭代器递增两次,恰好越过了新添加的元素和正在处理的元素,指向下一个未处理的元素。

3.3 不要保存end返回的迭代器

当我们添加/删除vector或string的元素后,或在deque中首元素之外任何位置添加/删除元素后,原来end返回的迭代器总是会失效。因此,添加或删除元素的循环程序必须反复调用end,而不能在循环之前保存end返回的迭代器,一直当作容器末尾使用。通常C++标准库的实现中end()操作都很快,部分就是因为这个原因。

例如,考虑这样一个循环,它处理容器中的每个元素,在其后添加一个新元素。我们希望循环能跳过新添加的元素,只处理原有元素。在每步循环之后,我们将定位迭代器,使其指向下一个原有元素。如果我们试图“优化”这个循环,在循环之前保存end()返回的迭代器,一直用作容器末尾,就会导致一场灾难:

// 灾难:此循环的行为是未定义的
auto begin = v.begin(),
     end = v.end(); // 保存尾迭代器的值是一个坏主意
while (begin != end)
{
	// 做一些处理
	// 插入新值,对begin重新赋值,否则的话它就会失效
	++begin; // 向前移动begin,因为我们想在此元素之后插入元素
	begin = v.insert(begin, 42); // 插入新值
	++begin; // 向前移动begin跳过我们刚刚加入的元素
}

此代码的行为是未定义的。在很多标准库实现上,此代码会导致无限循环。问题在于我们将end操作返回的迭代器保存在一个名为end的局部变量中。在循环体中,我们向容器中添加了一个元素,这个操作使保存在end中的迭代器失效了。这个迭代器不再指向v中任何元素,或是v中尾元素之后的位置。

如果在一个循环中插入/删除deque、string或vector中的元素,不要缓存end返回的迭代器。

必须在每次插入操作后重新调用end(),而不能在循环开始前保存它返回的迭代器:

// 更安全的方法:在每个循环步添加/删除元素后都重新计算end
while (begin != v.end()
{
    // 做一些处理
    ++begin; // 向前移动begin,因为我们想在此元素之后插入元素
    begin = v.insert(begin, 42); // 插入新值
    ++begin; // 向前移动begin,跳过我们刚刚加入的元素
}

4. 反向迭代器

4.1 反向迭代器的概念

反向迭代器就是在容器中从尾元素向首元素反向移动的迭代器。对于反向迭代器,递增(以及递减)操作的含义会颠倒过来。递增一个反向迭代器(++it)会移动到前一个元素;递减一个迭代器(--it)会移动到下一个元素。

除了forward_list之外,其他容器都支持反向迭代器。我们可以通过调用rbegin、rend、crbegin和 crend成员函数来获得反向迭代器。这些成员函数返回指向容器尾元素和首元素之前一个位置的迭代器。与普通迭代器一样,反向迭代器也有const和非const版本。

下图显示了一个名为vec的假设的vector上的4种迭代器:

下面的循环是一个使用反向迭代器的例子,它按逆序打印vec中的元素:

vector<int> vec = { 0,1,2,3,4,5,6,7,8,9 };
// 从尾元素到首元素的反向迭代器
for (auto r_iter = vec.crbegin(); // 将r_iter绑定到尾元素
		r_iter != vec.crend();    // crend指向首元素之前的位置
		++r_iter)                 // 实际是递减,移动到前一个元素
	cout << *r_iter << endl;      // 打印9,8,7,...,0

虽然颠倒递增和递减运算符的含义可能看起来令人混淆,但这样做使我们可以用算法透明地向前或向后处理容器。例如,可以通过向sort传递一对反向迭代器来将vector整理为递减序:

sort(vec.begin(), vec.end()); // 按“正常序”排序vec
// 按逆序排序:将最小元素放在vec的末尾
sort(vec.rbegin(), vec.rend());

4.2 反向迭代器需要递减运算符

不必惊讶,我们只能从既支持++也支持--的迭代器来定义反向迭代器。毕竟反向迭代器的目的是在序列中反向移动。除了forward_list之外,标准容器上的其他迭代器都既支持递增运算又支持递减运算。但是,流迭代器不支持递减运算,因为不可能在一个流中反向移动。因此,不可能从一个forward_list或一个流迭代器创建反向迭代器。

4.3 反向迭代器和其他迭代器间的关系

假定有一个名为line的string,保存着一个逗号分隔的单词列表,我们希望打印line中的第一个单词。使用find可以很容易地完成这一任务:

// 在一个逗号分隔的列表中查找第一个元素
auto comma = find(line.cbegin(), line.cend(), ',');
cout << string(line.cbegin(), comma) << endl;

如果line中有逗号,那么comma将指向这个逗号;否则,它将等于line.cend()。当我们打印从line.cbegin()到comma之间的内容时,将打印到逗号为止的字符,或者打印整个string(如果其中不含逗号的话)。

如果希望打印最后一个单词,可以改用反向迭代器:

// 在一个逗号分隔的列表中查找最后一个元素
auto rcomma = find(line.crbegin(), line.crend(), ',');

由于我们将crbegin()和crend()传递给find,find将从line的最后一个字符开始向前搜索。当find完成后,如果line中有逗号,则rcomma指向最后一个逗号——即,它指向反向搜索中找到的第一个逗号。如果line中没有逗号,则rcomma指向line.crend()。

当我们试图打印找到的单词时,最有意思的部分就来了。看起来下面的代码是显然的方法

// 错误:将逆序输出单词的字符
cout << string(line.crbegin(), rcomma) << endl;

但它会生成错误的输出结果。例如,如果我们的输入是

FIRST,MIDDLE,LAST

则这条语句会打印TSAL!

下图说明了问题所在:我们使用的是反向迭代器,会反向处理string。因此,上述输出语句从 crbegin开始反向打印line中内容。而我们希望按正常顺序打印从rcomma开始到line末尾间的字符。但是,我们不能直接使用rcomma。因为它是一个反向迭代器,意味着它会反向朝着string的开始位置移动。需要做的是,将rcomma转换回一个普通迭代器,能在line中正向移动。我们通过调用reverse_iterator的base成员函数来完成这一转换,此成员函数会返回其对应的普通迭代器:

// 正确:得到一个正向迭代器,从逗号开始读取字符直到line末尾
cout << string(rcomma.base(), line.cend()) << endl;

给定和之前一样的输入,这条语句会如我们的预期打印出LAST。

图中的对象显示了普通迭代器与反向迭代器之间的关系。例如,rcomma和rcomma.base()指向不同的元素,line.crbegin和line.cend()也是如此。这些不同保证了元素范围无论是正向处理还是反向处理都是相同的。

从技术上讲,普通迭代器与反向迭代器的关系反映了左闭合区间的特性。关键点在于[line.crbegin (), rcomma)和[rcomma.base(), line.cend())指向line中相同的元素范围。为了实现这一点,rcomma和rcomma.base()必须生成相邻位置而不是相同位置,crbegin()和cend()也是如此。

反向迭代器的目的是表示元素范围,而这些范围是不对称的,这导致一个重要的结果:当我们从一个普通迭代器初始化一个反向迭代器,或是给一个反向迭代器赋值时,结果迭代器与原迭代器指向的并不是相同的元素。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】迭代器 的相关文章

  • 隐式将 string 转换为 string_view

    void Foo1 string view view string str one two three Foo1 one two three Implicitly convert char to string view Foo1 str I
  • Qt:更改 Mac OS X 上的应用程序 QMenuBar 内容

    我的应用程序对多个 页面 使用 QTabWidget 其中顶级菜单根据用户所在的页面而变化 我的问题是 尝试重新创建菜单栏的内容会导致严重的显示问题 它在除 Mac OS X 之外的所有平台上按预期使用第一种和第三种样式 尚未测试第二种 但
  • 返回带有列表对象的列表对象

    我有三个表 汽车品牌 汽车型号 和 CarsandModel 我有 Carsand 模型表 因为一个模型可以由多个制造商构建 我想返回包含汽车型号列表的汽车品牌列表 我现在的长篇大论不是过滤汽车型号的汽车制造商列表 我尝试添加一个 wher
  • Java 相当于 C# 的 async/await?

    我是一名普通的 C 开发人员 但偶尔也会使用 Java 开发应用程序 我想知道 Java 中是否有相当于 C async await 的东西 简单来说 java 相当于 async Task
  • tmpnam 的 C/C++ 线程安全性?

    我需要使用tmpnamC 中的函数 但我需要了解它的线程安全性 也就是说 如果我有多个线程 每个线程都需要为临时文件获取不同的名称 我是否可以保证每个线程都会收到具有不同名称的文件 tmpnam 仅保证该文件当时不存在 但它可能会在您自己创
  • 如何使用 LINQ 对列表的列表进行分组(例如:List>)

    我知道我可以使用一些 for 循环轻松地做到这一点 但想看看是否有一种方法可以使用流畅的 LINQ 来做到这一点 我试图找出每个子列表中有多少个 我在看Enumerable SequenceEqual http msdn microsoft
  • MPI_Gather 分段错误

    我有这个并行高斯消除代码 调用以下任一方法时会发生分段错误MPI Gather函数调用 我知道如果没有为任一缓冲区正确分配内存 可能会出现此类错误 但我看不出内存管理代码有什么问题 有人可以帮忙吗 Thanks Notes 该程序从一个 t
  • 清理 STL 指针列表/向量

    您可以想出的最短的 C 块是多少来安全地清理std vector or std list指针 假设您必须对指针调用删除 list
  • 如何在提升日期时间中忽略周末和节假日?

    第一个问题 我有一个提升日期对象 如下所示 boost gregorian date 今天 2012 02 13 我从今天减去日期部分 如下所示 今天 月 240 或今天 天 X 等 我想在进行上述减法时是否有办法排除周末和特殊假期 我的意
  • Web API 2 中的方法名称约定 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 是否有 Web API 2 中使用的约定的列表 以这两种方法为例 两者都可以工作 但都没有用属性来装饰 IHttpActionResu
  • 如何防止打印屏幕

    我有一个要求 我正在开发的应用程序阻止用户轻松捕获屏幕内容 我已经表示 没有可行的方法可以完全防止这种情况发生 但我正在寻找方法来为这一过程引入一些障碍 我正在使用 C NET 2 0 和 WinForms 你不能 您能做的最好的事情就是在
  • 将 boost::iostreams::mapped_file_source 与 std::multimap 一起使用

    我有相当大量的数据需要分析 每个文件大约有 5gig 每个文件的格式如下 xxxxx yyyyy 键和值都可以重复 但键是按升序排列的 我正在尝试使用内存映射文件来实现此目的 然后找到所需的键并使用它们 这是我写的 if data file
  • 在.NET MVC中,有没有一种简单的方法来检查我是否在主页上?

    如果用户从主页登录 我需要采取特定的操作 在我的 LogOnModel 中 我有一个隐藏字段 Html Hidden returnUrl Request Url AbsoluteUri 在我的控制器中 我需要检查该值是否是主页 在下面的示例
  • 将 LPTSTR 转换为要写入文件的字符串或 char *

    我想将 LPTSTR 转换为字符串或 char 以便能够使用 ofstream 将其写入文件 有任何想法吗 Use T2A http msdn microsoft com en us library 87zae4a3 VS 80 aspx宏
  • Visual Studio 扩展找不到所需的程序集

    我为 Visual Studio 2013 编写了一个扩展 因为该死的组合框错误 https stackoverflow com questions 7800032 cancel combobox selection in wpf with
  • 是否可以在 ASP.NET Web API 和 SPA 中使用基于 cookie 的身份验证?

    我想创建基于 angularjs 前端和 ASP NET Web API 的 Web 应用程序 我需要创建安全 api 但我无法在将实施此 Web 应用程序的公司服务器上使用基于令牌的身份验证 是否可以对 SPA 和 ASP NET Web
  • timeval_subtract 解释

    使用 timeval subtract 函数来查找两个 struct timeval 类型之间经过的时间 有人可以解释一下用于 通过更新 y 执行后续减法的进位 和其他部分的目的和逐步数学吗 我了解该函数的目的以及如何在程序中实现它 但我想
  • Windows 中的蓝牙 AVRCP 命令会触发哪些事件

    可以这么说 只是在做一些高级侦察 对于我的潘多拉客户 Elpis http elpis adamhaile net 我支持全局媒体键 键盘上的 MediaPlayPause MediaNext 等 并且我希望能够支持AVRCP http e
  • (int *)0 是空指针吗?

    这可以被认为是一个扩展这个问题 https stackoverflow com q 16563114 912144 我只对 C 感兴趣 但添加 C 来完成扩展 C11 标准 6 3 2 3 3 规定 值为 0 的整数常量表达式 或此类表达式
  • printf 右对齐括号内的数字

    我正在编写一个程序 显示数组中的所有信息 它必须以括号中的数组索引开头 例如 2 并且它们必须彼此正确对齐 如果只是数字 我知道你可以这样做 printf 10d index 但是用括号括起来会得到以下输出 1 2 10 11 当我真正希望

随机推荐

  • 关于CentOS7虚拟机配置静态IP地址及ping不通通百度等官网

    一 IP地址的配置 1 查看MAC地址 点击 虚拟机 gt gt gt 设置 gt gt gt 网络适配器 gt gt gt 高级 gt gt gt 记住MAC地址 后面会用到 2 查看子网掩码和网关IP 点击 编辑 gt gt gt 虚拟
  • Vue极简使用

    Vue 安装Vue 模板语法 安装Vue 安装nodejs 这里我安装的是14 5 4版本 https nodejs org download release v14 15 4 解压后配置一下环境变量就行 安装cnpm镜像 这个安装的版本可
  • python小游戏——走出迷宫代码开源

    作者 小刘在C站 个人主页 小刘主页 每天分享云计算网络运维课堂笔记 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 夕阳下 是最美的 绽放 愿所有的美好 再疫情结束后如约而至 目录 一 游戏代码效果呈现 二 游戏主代码 1
  • 矩阵运算(一)最小二乘法

    最小二乘法 前言 最小二乘法拟合一元多项式的简单推导 进一步的思考 CPP开发者封装最小二乘法 QR分解 Matlab中使用QR分解 Python numpy中使用 参考文献 作者说 前言 最小二乘法在函数拟合的过程中广为应用 不少读者使用
  • Spring Boot Maven Plugin -- repackage目标;spring-boot-maven-plugin的executable配置

    Spring Boot Maven Plugin repackage目标 Spring Boot Maven Plugin插件提供spring boot在maven中的支持 允许你打包可运行的jar包或war包 插件提供了几个maven目标
  • nginx server.conf demo

    server access log Users xx software nginx logs access log error log Users xx software nginx logs error log listen 50001
  • 大数据毕设 - 深度学习安全帽佩戴检测系统(python OpenCV yolov5)

    文章目录 0 前言 1 课题背景 2 效果演示 3 Yolov5框架 4 数据处理和训练 4 1 安全帽检测 4 2 检测危险区域内是否有人 5 最后 0 前言 Hi 大家好 这里是丹成学长的毕设系列文章 对毕设有任何疑问都可以问学长哦 这
  • rke2 在线部署 kubernetes

    文章目录 1 还原虚拟机 2 背景 3 介绍 4 预备条件 5 1 配置网卡 5 配置主机名 6 配置互信 7 安装 ansible 8 系统初始化 9 kube master01 部署 9 1 定制配置文件 可选 9 2 部署 9 3 命
  • 微信二维码的生成(java后端)--邀请新人

    目录 写在前言 1 微信官方文档 2 具体分析 写在前言 最近因为在学习微信小程序邀请新用户的功能 所以需要后端生成二维码并且携带本人的用户id或者其他的信息 传给前端 用户通过这个二维码去进行登录或者其他的操作 这时候前端人员记录下来邀请
  • Qt 2D绘图坐标系统

    一 坐标系简介 Qt中每一个窗口都有一个坐标系 默认的 窗口左上角为坐标原点 然后水平向右依次增大 水平向左依次减小 垂直向下依次增大 垂直向上依次减小 原点即为 0 0 点 然后以像素为单位增减 例如 void Dialog paintE
  • Qt之QGraphicsView实战篇

    作者 billy 版权声明 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 前言 前面的章节介绍了 Graphics View 绘图架构 终于到实战了 真的是千呼万唤始出来 这一章节就用 Graphics View 绘图
  • 第二章:Matplotlib之艺术画笔见乾坤

    第二章 艺术画笔见乾坤 一 概述 1 matplotlib的三层api matplotlib的原理或者说基础逻辑是 用Artist对象在画布 canvas 上绘制 Render 图形 就和人作画的步骤类似 准备一块画布或画纸 准备好颜料 画
  • Tomcat重启单个服务

    一个tomcat中有多个服务 每次为了重启某个服务 需要重新启动Tomcat 会影响其他服务的正常运行 可通过以下方式进行设置 进入Tomcat服务管理页面 对单个服务进行管理 1 首先我们启动tomcat 访问主页 可以看到右上位置有三个
  • MYSQL--基础--10--慢查询日志

    MYSQL 基础 10 慢查询日志 1 是什么 是MySQL提供的一种日志记录 支持将日志记录写入文件 将SQL查询时间超过 大于 设置阈值的语句 记录到慢查询日志中 2 查看语句 2 1 慢日志是否开启和日志文件位置 show varia
  • 【yolo】yolov5-seg实例分割标签

    文章目录 前言 yolo标签 yolov5 seg标签 转换代码 前言 不同于以往的yolo数据 用的是目标框的label 再加上语义标签 yolov5 seg中用的标签只有一个语义标签 没有目标框的标签 具体对比如下 yolo标签 1 目
  • java 获取月份 几周_java – 我想在特定的月份获得几周的时间

    Calendar类的WEEK OF YEAR属性可能对您有用 参考 Calendar class 创建一个新的日期 将是一个月的第一天 得到这一天的一周的这个星期 让你说起点价值 创建一个新的日期 这将是给定月份的最后一天 获得今年的一周
  • FastCFS核心组件FastStore架构及特点

    FastCFS核心组件FastStore架构及特点 本篇文章转载于 FastCFS 作者 余庆 大佬的 FastDFS分享与交流 公众号 上一篇文章介绍了 FastCFS 服务端两大核心组件 FastDIR 和 FastStore 其中 F
  • python文本数据处理_Python文本数据分析与处理

    Python文本数据分析与处理 新闻摘要 分词 使用jieba分词 注意lcut只接受字符串 过滤停用词 TF IDF得到摘要信息或者使用LDA主题模型 TF IDF有两种 jieba analyse extract tags conten
  • Linux中su、su -和sudo的区别

    su 切换到root用户 但是并没有转到root用户家目录下 即没有改变用户的环境 su 切换到root用户 并转到root用户的家目录下 即改变到了root用户的环境 这个涉及到不同用户下的环境变量的配置 sudo 通过sudo 我们能把
  • 【C++】迭代器

    目录 1 迭代器 1 1 迭代器的操作 1 2 迭代器范围 1 3 使用左闭合范围蕴含的编程假定 2 begin和end成员 3 容器操作可能使迭代器失效 3 1 迭代器失效 3 2 编写改变容器的循环程序 3 3 不要保存end返回的迭代