【C++之STL】008序列容器篇deque非更易型操作

c.empyt()

在C++中,std::deque(双端队列)是一个模板类,用于存储可变大小的对象序列。std::deque 提供了一系列成员函数来操作和管理这个序列。其中,empty() 是 std::deque 的一个成员函数,用于检查双端队列是否为空。

empty() 函数返回一个布尔值,如果 std::deque 中没有任何元素,那么它返回 true,否则返回 false。

下面是一个使用 empty() 函数的简单示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque;

    // 检查双端队列是否为空
    if (myDeque.empty()) {
        std::cout << "Deque is empty." << std::endl;
    } else {
        std::cout << "Deque is not empty." << std::endl;
    }

    // 向双端队列中添加元素
    myDeque.push_back(1);
    myDeque.push_front(2);

    // 再次检查双端队列是否为空
    if (myDeque.empty()) {
        std::cout << "Deque is still empty." << std::endl;
    } else {
        std::cout << "Deque is now not empty." << std::endl;
    }

    return 0;
}

这个示例中,我们首先创建了一个空的 std::deque,然后使用 empty() 函数检查它是否为空。接着,我们向双端队列中添加了两个元素,并再次使用 empty() 函数来验证双端队列现在是否不为空。

输出将会是:

Deque is empty.
Deque is now not empty.

empty() 函数在检查容器是否为空时非常有用,尤其是在进行容器操作之前,你通常需要确保容器不是空的,以避免未定义的行为。

c.size()

在C++中,std::deque(双端队列)是一个模板类,它支持在序列的两端进行快速的插入和删除操作。size() 是 std::deque 的一个成员函数,用于返回容器中当前存储的元素数量。

size() 函数返回一个 size_t 类型的值,表示容器中元素的个数。size_t 是一个无符号整数类型,通常用于表示大小或计数。

下面是一个使用 size() 函数的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque;

    // 添加元素到双端队列
    myDeque.push_back(1);
    myDeque.push_back(2);
    myDeque.push_front(3);

    // 获取并输出双端队列的大小
    std::cout << "Size of deque: " << myDeque.size() << std::endl;

    // 从双端队列中删除一个元素
    myDeque.pop_back();

    // 再次获取并输出双端队列的大小
    std::cout << "Size of deque after pop_back: " << myDeque.size() << std::endl;

    return 0;
}

输出将会是:

Size of deque: 3
Size of deque after pop_back: 2

在这个示例中,我们首先创建了一个空的 std::deque,然后向其中添加了三个元素。通过调用 size() 函数,我们得知双端队列的大小为3。接着,我们从双端队列的尾部删除一个元素,然后再次调用 size() 函数,这次返回的大小为2,因为双端队列中现在只剩下两个元素。

size() 函数在需要知道容器中当前有多少元素时非常有用,比如在循环中遍历元素或者在执行某些需要知道容器大小的操作时。

c.max_size()

在C++中,std::deque(双端队列)的max_size()成员函数返回容器可能持有的最大元素数量。这个值是由实现定义的,并且通常受到可用内存的限制。理论上,max_size()应该返回一个非常大的数,足以满足日常编程的需求。

max_size()对于了解容器在特定系统上的限制非常有用,尽管在实际情况中,你可能很少会遇到需要处理这么多元素的情况。它主要用于在编程时确保你的代码不会因为尝试存储超出容器容量的元素而导致未定义行为。

下面是一个使用max_size()的简单示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque;

    // 获取并输出双端队列的最大可能大小
    std::cout << "Maximum possible size of deque: " << myDeque.max_size() << std::endl;

    return 0;
}

这个示例创建了一个空的std::deque,并使用max_size()来获取并输出该容器可能包含的最大元素数量。

需要注意的是,尽管max_size()提供了一个理论上的上限,但在实际编程中,尝试接近或达到这个限制可能会导致性能问题或内存耗尽。通常,你应该设计你的程序以避免需要存储这么多元素,或者至少要在达到这个限制之前采取适当的措施,比如使用分页、分块处理数据,或者通知用户等。

c.shrink_to_fit()

在C++中,std::deque(双端队列)的shrink_to_fit()成员函数尝试减少容器内部用于存储元素的内存量,以更紧密地匹配当前元素数量。这样做可以释放未使用的内存,从而可能提高内存使用效率。

shrink_to_fit()不保证实际减少容器的大小(即,不保证capacity()减少),但通常会尝试这样做。如果成功减少内存使用量,则该函数返回true;如果由于实现限制或其他原因无法减少内存,则返回false。

下面是一个使用shrink_to_fit()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque;

    // 向双端队列中添加一些元素
    for (int i = 0; i < 10; ++i) {
        myDeque.push_back(i);
    }

    // 获取并输出当前容量
    std::cout << "Capacity before shrink_to_fit: " << myDeque.capacity() << std::endl;

    // 尝试减少内存使用量
    if (myDeque.shrink_to_fit()) {
        std::cout << "Successfully reduced memory usage." << std::endl;
    } else {
        std::cout << "Could not reduce memory usage." << std::endl;
    }

    // 再次获取并输出当前容量
    std::cout << "Capacity after shrink_to_fit: " << myDeque.capacity() << std::endl;

    return 0;
}

在这个示例中,我们首先创建了一个std::deque并向其中添加了一些元素。然后,我们调用shrink_to_fit()尝试减少内存使用量,并输出操作结果以及操作前后的容量。

需要注意的是,shrink_to_fit()并不保证减少到正好匹配当前元素数量的容量,它只是尝试这样做。在某些实现中,shrink_to_fit()可能无法减少容量,尤其是当容器的大小经常变化时,实现可能会保留一些额外的容量以优化未来的插入操作。

此外,频繁地调整容器的容量可能会导致性能下降,因为每次调整都可能涉及到内存的重新分配和数据的复制。因此,通常建议仅在必要时调用shrink_to_fit(),例如在知道容器将不再增长或增长很少的情况下。

c[idx]

在C++中,std::deque(双端队列)支持使用数组下标运算符([])来访问其元素。这意味着你可以使用c[idx]的形式来访问双端队列c中索引为idx的元素。

请注意,使用下标运算符访问元素时,必须确保索引idx是有效的。有效的索引范围是从0到c.size() - 1。如果尝试访问超出这个范围的索引,程序将会发生未定义行为,通常这会导致程序崩溃。

下面是一个使用[]运算符访问std::deque元素的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用下标运算符访问元素
    int firstElement = myDeque[0];
    int lastElement = myDeque[myDeque.size() - 1];

    // 输出访问到的元素
    std::cout << "First element: " << firstElement << std::endl;
    std::cout << "Last element: " << lastElement << std::endl;

    // 尝试访问超出范围的索引(未定义行为)
    // int invalidElement = myDeque[myDeque.size()]; // 这将导致错误

    return 0;
}

在这个示例中,我们创建了一个包含5个整数的std::deque。我们使用[]运算符来访问第一个元素(索引为0)和最后一个元素(索引为size() - 1)。然后,我们输出这些元素的值。

请注意,注释掉的那一行代码尝试访问一个超出范围的索引,这是不正确的,并且会导致未定义行为。在实际编程中,你应该总是确保你访问的索引是有效的。

使用下标运算符访问元素是一种快速且直接的方式来访问容器中的元素,但它不提供边界检查。如果你需要确保索引有效,可以先使用size()函数来检查索引是否在有效范围内。

c.at(idx)

在C++中,std::deque的at()成员函数提供了一种访问容器中指定位置元素的方法,同时它还执行边界检查,以确保提供的索引在有效范围内。如果索引超出范围,at()会抛出一个std::out_of_range异常。

使用at()函数比直接使用[]运算符更安全,因为at()会在索引无效时通知你,而[]运算符则不会进行任何边界检查,这可能导致未定义行为。

下面是使用at()函数的一个示例:

#include <iostream>
#include <deque>
#include <stdexcept>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用at()访问元素
    try {
        int element = myDeque.at(2); // 访问索引为2的元素,即30
        std::cout << "Element at index 2: " << element << std::endl;

        // 尝试访问超出范围的索引
        int invalidElement = myDeque.at(myDeque.size()); // 这将抛出std::out_of_range异常
    } catch (const std::out_of_range& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

在这个示例中,我们首先使用at()函数访问了索引为2的元素,这是有效的,并且我们输出了该元素的值。然后,我们尝试访问一个超出范围的索引(即myDeque.size()),这将导致std::out_of_range异常被抛出,并被我们的catch块捕获。

使用try和catch块来捕获异常是一种好的做法,因为它允许你优雅地处理错误,而不是让程序崩溃。在实际编程中,你可能希望根据具体情况采取不同的错误处理策略。

c.front()

在C++中,std::deque(双端队列)的front()成员函数返回对队列中第一个元素的引用。如果队列为空,调用front()会导致未定义行为,通常表现为程序崩溃。因此,在使用front()之前,你应该确保队列不为空,可以通过检查empty()函数的返回值来实现这一点。

下面是一个使用front()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque;

    // 向双端队列中添加一些元素
    myDeque.push_back(10);
    myDeque.push_back(20);
    myDeque.push_back(30);

    // 检查队列是否为空
    if (!myDeque.empty()) {
        // 获取并输出队列中的第一个元素
        int firstElement = myDeque.front();
        std::cout << "The first element is: " << firstElement << std::endl;
    } else {
        std::cout << "The deque is empty." << std::endl;
    }

    return 0;
}

在这个示例中,我们首先创建了一个std::deque并向其中添加了一些元素。然后,我们检查队列是否为空,如果不为空,我们就使用front()来获取并输出队列中的第一个元素。

请注意,由于std::deque是一个双端队列,front()返回的是队列开头的元素,而back()则返回队列末尾的元素。这种特性使得std::deque在需要频繁在两端添加或删除元素时非常高效。

c.back()

在C++中,std::deque(双端队列)的back()成员函数返回对队列中最后一个元素的引用。这意味着你可以使用back()来直接访问并操作双端队列的最后一个元素。

如果双端队列c是空的,调用back()将会导致未定义行为,通常表现为程序崩溃。因此,在使用back()之前,你应该确保双端队列不为空,这可以通过检查empty()函数的返回值来实现。

下面是一个使用back()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque;

    // 向双端队列中添加一些元素
    myDeque.push_back(10);
    myDeque.push_back(20);
    myDeque.push_back(30);

    // 检查队列是否为空
    if (!myDeque.empty()) {
        // 获取并输出队列中的最后一个元素
        int lastElement = myDeque.back();
        std::cout << "The last element is: " << lastElement << std::endl;

        // 修改队列中的最后一个元素
        myDeque.back() = 40;
        std::cout << "After modifying, the last element is: " << myDeque.back() << std::endl;
    } else {
        std::cout << "The deque is empty." << std::endl;
    }

    return 0;
}

在这个示例中,我们首先创建了一个std::deque并向其中添加了一些元素。然后,我们检查队列是否为空,如果不为空,我们就使用back()来获取并输出队列中的最后一个元素。接下来,我们直接通过back()修改了队列中的最后一个元素,并再次输出以显示修改后的结果。

back()函数对于需要在双端队列末尾快速添加或修改元素的场景特别有用,因为它提供了直接访问最后一个元素的能力。

c.begin()

在C++中,std::deque的begin()成员函数返回一个指向容器中第一个元素的迭代器。这个迭代器可以被用来访问和修改容器中的元素。如果容器为空,begin()返回的迭代器将等于end()返回的迭代器。

begin()是一个常量时间复杂度的操作,这意味着无论容器中有多少元素,获取第一个元素的迭代器所花费的时间都是恒定的。

下面是一个使用begin()函数的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用begin()获取指向第一个元素的迭代器
    std::deque<int>::iterator it = myDeque.begin();

    // 使用迭代器访问和输出第一个元素
    if (it != myDeque.end()) {
        std::cout << "The first element is: " << *it << std::endl;

        // 使用迭代器访问和输出第二个元素
        ++it;
        if (it != myDeque.end()) {
            std::cout << "The second element is: " << *it << std::endl;
        }
    } else {
        std::cout << "The deque is empty." << std::endl;
    }

    return 0;
}

在这个示例中,我们首先创建了一个包含一些整数的std::deque。然后,我们使用begin()获取了一个指向第一个元素的迭代器,并使用这个迭代器来访问和输出第一个元素。接着,我们递增迭代器以访问第二个元素,并再次检查迭代器是否不等于end()以确保它没有超出范围。

begin()返回的迭代器可以被用来遍历整个容器,通过递增迭代器可以逐个访问容器中的元素,直到迭代器等于end()为止。这种遍历容器的方式在C++中非常常见,也是处理容器数据的有效方法。

c.end()

在C++中,std::deque的end()成员函数返回一个迭代器,该迭代器指向容器中的“最后一个元素之后”的位置。请注意,这个迭代器并不指向容器的最后一个元素,而是指向最后一个元素之后的位置。因此,它不能被解引用。

end()迭代器常常用于循环中,以标记遍历容器的结束点。例如,当使用范围基础的for循环(也称为C++11 for-each循环)或传统的for循环来遍历std::deque时,end()用于确定何时停止迭代。

这里是一个使用end()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用end()在for循环中遍历deque
    for (std::deque<int>::iterator it = myDeque.begin(); it != myDeque.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 使用范围基础的for循环遍历deque
    for (const auto& element : myDeque) {
        std::cout << element << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个示例中,我们首先使用传统的for循环和begin()、end()迭代器来遍历myDeque。然后,我们使用范围基础的for循环来遍历同一个deque。在范围基础的for循环中,我们不需要显式地使用begin()和end(),因为循环会自动处理这些细节。

end()返回的迭代器常用于比较,以确定是否已经到达了容器的末尾。在遍历容器时,一旦迭代器等于end(),就意味着遍历已经完成,不应继续解引用该迭代器。

c.cbegin()

在C++中,std::deque的cbegin()成员函数返回一个指向容器中第一个元素的常量迭代器(const iterator)。这个迭代器允许你读取容器中的元素,但不允许你修改它们。cbegin()是C++11引入的,它的作用是提供一个常量迭代器,从而明确表明你不打算通过该迭代器修改容器中的元素。

使用cbegin()的一个好处是,它增强了代码的可读性和意图的明确性。当你使用cbegin()时,你告诉读者(以及未来的你)这个迭代器将不会用于修改容器。

下面是一个使用cbegin()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用cbegin()获取指向第一个元素的常量迭代器
    auto it = myDeque.cbegin();

    // 使用迭代器访问第一个元素并输出
    if (it != myDeque.cend()) {
        std::cout << "The first element is: " << *it << std::endl;

        // 尝试通过迭代器修改元素(这将导致编译错误)
        // *it = 100; // 错误:不能通过常量迭代器修改元素
    } else {
        std::cout << "The deque is empty." << std::endl;
    }

    return 0;
}

在这个示例中,我们使用cbegin()获取了一个指向myDeque中第一个元素的常量迭代器,并使用了这个迭代器来读取第一个元素的值。注意,我们试图通过*it = 100;来修改元素的值,这将导致编译错误,因为我们使用的是常量迭代器。

cbegin()和cend()通常用于范围基础的for循环中,以确保在循环内部不会修改容器的内容。例如:

for (const auto& element : myDeque) {
    std::cout << element << " ";
}

在这个范围基础的for循环中,element是一个常量引用,它对应于容器中的每个元素。由于element是常量,你不能在循环内部修改它。这种写法隐式地使用了cbegin()和cend(),因为循环需要常量迭代器来遍历容器。

c.cend()

在C++中,std::deque的cend()成员函数返回一个指向容器中“最后一个元素之后”位置的常量迭代器(const iterator)。与end()函数类似,cend()也不指向容器的最后一个元素,而是指向最后一个元素之后的位置,因此它也不能被解引用。

cend()主要用于提供对容器内容的只读访问,确保通过该迭代器不能修改容器中的任何元素。这在编写泛型代码时特别有用,因为你可能不知道容器是否可以被修改,或者你可能想要明确表明你的代码不会修改容器。

cend()通常与基于范围的for循环或算法一起使用,当你想要遍历容器但不修改其内容时。

下面是一个使用cend()的示例:

#include <iostream>
#include <deque>
#include <algorithm>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用cend()确保我们不会修改deque
    for (const auto& element : myDeque) {
        std::cout << element << " ";
    }
    std::cout << std::endl;

    // 使用cend()与std::find算法一起查找元素
    auto it = std::find(myDeque.cbegin(), myDeque.cend(), 30);

    if (it != myDeque.cend()) {
        std::cout << "Found element 30 at position: " << std::distance(myDeque.cbegin(), it) << std::endl;
    } else {
        std::cout << "Element 30 not found in the deque." << std::endl;
    }

    return 0;
}

在这个示例中,我们使用cend()与基于范围的for循环一起遍历myDeque,并输出每个元素。我们还使用cend()作为std::find算法的结束迭代器来查找值为30的元素。

注意,虽然cend()返回一个常量迭代器,但begin()返回的是一个非常量迭代器。因此,在遍历过程中,如果你使用begin()而非cbegin(),你将能够通过迭代器修改deque中的元素。然而,使用cend()作为结束条件将确保你的代码不会尝试修改容器。

c.rbegin()

在C++中,std::deque的rbegin()成员函数返回一个逆向迭代器(reverse iterator),该迭代器指向容器中的“最后一个元素”。与正向迭代器不同,逆向迭代器允许你从容器的末尾开始向前遍历容器。

rbegin()常用于需要从后向前处理容器的场景,例如查找最后一个满足特定条件的元素,或者在不知道容器长度的情况下反向遍历容器。

下面是一个使用rbegin()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用rbegin()从后向前遍历deque
    for (auto it = myDeque.rbegin(); it != myDeque.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 查找最后一个大于30的元素
    auto it = std::find_if(myDeque.rbegin(), myDeque.rend(), [](int n) { return n > 30; });
    if (it != myDeque.rend()) {
        std::cout << "The last element greater than 30 is: " << *it << std::endl;
    } else {
        std::cout << "No elements greater than 30 found." << std::endl;
    }

    return 0;
}

在这个示例中,我们首先使用rbegin()和rend()来反向遍历myDeque,并输出每个元素。然后,我们使用std::find_if算法和逆向迭代器来查找最后一个大于30的元素。

注意,rend()返回一个指向容器中“第一个元素之前”位置的逆向迭代器。它类似于正向迭代器的begin(),但用于逆向迭代。因此,当逆向迭代器等于rend()时,表示已经到达了容器的开始之前的位置,即遍历结束。

与rbegin()对应的常量逆向迭代器是crbegin(),它返回一个指向容器中最后一个元素的常量逆向迭代器,不允许通过该迭代器修改容器中的元素。

c.rend()

在C++中,std::deque的rend()成员函数返回一个逆向迭代器(reverse iterator),该迭代器指向容器中“第一个元素之前”的位置。换句话说,rend()返回的逆向迭代器指向的是逆序遍历时的“结束”位置,这个位置在逻辑上位于容器的第一个元素之前。

逆向迭代器用于从后向前遍历容器,而rend()类似于正向迭代器的end()。不过,与end()不同,rend()返回的逆向迭代器不能解引用,也就是说,你不能通过它来获取容器中的元素值。

rend()通常用于标记逆向遍历的结束条件,在循环或算法中检查是否达到了逆序遍历的终点。

下面是一个使用rend()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用rbegin()和rend()逆向遍历deque
    for (auto it = myDeque.rbegin(); it != myDeque.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 使用std::find_if和逆向迭代器查找第一个小于30的元素
    auto it = std::find_if(myDeque.rbegin(), myDeque.rend(), [](int n) { return n < 30; });
    if (it != myDeque.rend()) {
        std::cout << "The first element less than 30 is: " << *it << std::endl;
    } else {
        std::cout << "No elements less than 30 found." << std::endl;
    }

    return 0;
}

在这个示例中,我们使用rbegin()和rend()来逆向遍历myDeque,并输出每个元素。然后,我们使用std::find_if算法和逆向迭代器来查找第一个小于30的元素。

注意,当你使用逆向迭代器时,rend()返回的迭代器是检查循环结束条件的正确方式。如果你尝试使用rbegin()作为结束条件,循环将永远不会结束,因为rbegin()始终指向容器的最后一个元素。

c.crbegin()

在C++中,std::deque的crbegin()成员函数返回一个指向容器中“最后一个元素”的常量逆向迭代器(const reverse iterator)。这个迭代器允许你逆序遍历容器,但不允许你通过它来修改容器中的元素。

crbegin()通常用于需要从后向前处理容器内容的场景,同时确保代码不会修改容器。当你想要逆序遍历容器但不想(或不能)修改其中的元素时,就会使用crbegin()。

下面是一个使用crbegin()的示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用crbegin()从后向前遍历deque
    for (auto it = myDeque.crbegin(); it != myDeque.crend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 使用crbegin()和std::find_if查找最后一个大于30的元素
    auto it = std::find_if(myDeque.crbegin(), myDeque.crend(), [](int n) { return n > 30; });
    if (it != myDeque.crend()) {
        std::cout << "The last element greater than 30 is: " << *it << std::endl;
    } else {
        std::cout << "No elements greater than 30 found." << std::endl;
    }

    return 0;
}

在这个示例中,我们使用crbegin()和crend()来逆序遍历myDeque,并输出每个元素。我们还使用crbegin()和crend()作为std::find_if算法的迭代器范围来查找最后一个大于30的元素。

注意,crend()返回一个指向容器中“第一个元素之前”位置的常量逆向迭代器。因此,当逆向迭代器等于crend()时,表示已经到达了容器的开始之前的位置,即遍历结束。

使用crbegin()和crend()可以确保你的代码不会意外地修改容器,这在处理不应该被修改的容器(例如,由其他线程或外部代码共享的容器)时特别有用。

c.crend()

在C++中,std::deque的crend()成员函数返回一个指向容器中“第一个元素之前”位置的常量逆向迭代器(const reverse iterator)。这个迭代器是常量的,意味着你不能通过它来修改容器中的任何元素。crend()通常用于标记逆向遍历的结束条件。

crend()与rend()类似,但crend()返回的迭代器是常量的,因此它不能被用来修改容器的内容。这在你需要遍历容器但不应该或不能修改其内容的情况下非常有用。

下面是使用crend()的一个例子:

#include <iostream>
#include <deque>
#include <algorithm>

int main() {
    std::deque<int> myDeque = {10, 20, 30, 40, 50};

    // 使用crend()来安全地遍历并输出deque中的元素
    for (auto it = myDeque.crbegin(); it != myDeque.crend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 使用std::find_if和crend()来查找最后一个大于30的元素
    auto it = std::find_if(myDeque.crbegin(), myDeque.crend(), [](int n) { return n > 30; });
    if (it != myDeque.crend()) {
        std::cout << "The last element greater than 30 is: " << *it << std::endl;
    } else {
        std::cout << "No elements greater than 30 found." << std::endl;
    }

    // 尝试通过crend()解引用将导致编译错误
    // int lastElement = *myDeque.crend(); // 错误!

    return 0;
}

在这个例子中,我们使用crbegin()和crend()来安全地遍历并输出myDeque中的元素,而不必担心会不小心修改它们。我们还使用std::find_if和crend()来查找最后一个大于30的元素。

请注意,尝试解引用crend()将导致编译错误,因为它指向的是容器中第一个元素之前的位置,解引用它是未定义的行为。

总的来说,crend()提供了一种安全的方式来标记逆向遍历的结束,同时确保代码不会意外地修改容器的内容。

c1 == c2

在C++中,std::deque(双端队列)的相等运算符==用于比较两个deque容器是否相等。当且仅当两个deque容器具有相同数量的元素,并且每个对应位置的元素都相等时,这两个deque容器才被认为是相等的。

这里是std::deque相等运算符==的一个基本用法示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> c1 = {1, 2, 3, 4, 5};
    std::deque<int> c2 = {1, 2, 3, 4, 5};
    std::deque<int> c3 = {1, 2, 3, 4, 6};

    // 检查c1和c2是否相等
    if (c1 == c2) {
        std::cout << "c1 is equal to c2" << std::endl;
    } else {
        std::cout << "c1 is not equal to c2" << std::endl;
    }

    // 检查c1和c3是否相等
    if (c1 == c3) {
        std::cout << "c1 is equal to c3" << std::endl;
    } else {
        std::cout << "c1 is not equal to c3" << std::endl;
    }

    return 0;
}

在这个示例中,c1和c2包含相同的元素,所以c1 == c2的结果为true,程序将输出c1 is equal to c2。然而,c1和c3包含不同的元素(最后一个元素不同),所以c1 == c3的结果为false,程序将输出c1 is not equal to c3。

请注意,相等运算符==执行的是元素级别的比较,它会比较deque中每个对应位置的元素。此外,如果两个deque容器的大小不同,它们肯定不相等,因为它们的元素数量已经不同。

如果你想进行元素级别的比较,但忽略元素的顺序,你需要自己实现一个比较函数或算法,因为std::deque的==运算符不会为你处理这种情况。

c1 != c2

在C++中,std::deque(双端队列)容器提供了一个operator!=成员函数,用于比较两个deque对象是否不相等。当且仅当两个deque对象不相等时,operator!=返回true。这通常意味着两个deque对象的大小不同,或者即使大小相同,它们的元素在至少一个位置上不相等。

以下是std::deque的operator!=用法的一个示例:

#include <iostream>
#include <deque>

int main() {
    std::deque<int> c1 = {1, 2, 3};
    std::deque<int> c2 = {1, 2, 3};
    std::deque<int> c3 = {1, 2, 4};

    // 检查c1和c2是否不相等
    if (c1 != c2) {
        std::cout << "c1 is not equal to c2" << std::endl;
    } else {
        std::cout << "c1 is equal to c2" << std::endl;
    }

    // 检查c1和c3是否不相等
    if (c1 != c3) {
        std::cout << "c1 is not equal to c3" << std::endl;
    } else {
        std::cout << "c1 is equal to c3" << std::endl;
    }

    return 0;
}

在这个例子中,c1和c2包含相同的元素,所以c1 != c2的结果为false,程序将输出c1 is equal to c2。然而,c1和c3在最后一个元素上不同,因此c1 != c3的结果为true,程序将输出c1 is not equal to c3。

std::deque的operator!=是通过比较两个deque的大小和对应位置的元素来实现的。如果两个deque的大小不同,或者即使大小相同但对应位置的元素不相等,那么它们就被认为是不相等的。

如果你没有为自定义类型重载operator!=,那么默认的行为可能并不适用于你的类。在这种情况下,你可能需要为你的类提供operator!=的实现,以确保它能够正确地比较两个对象是否不相等。

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊猫Devin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值