c++STL-通用(反向)迭代器适配器

c++STL-通用(反向)迭代器适配器

反向迭代器原理

建议先看c++STL-string的使用-CSDN博客c++STL-list的使用和迭代器-CSDN博客

可以用正向迭代器适配出反向迭代器。

cpp 复制代码
//三个模板参数分别是
//迭代器,有效数据的引用,有效数据的地址类型
template<class Iterator, class Ref, class Ptr>
class reverse_iterator{
    //...
};

Iterator是其他容器的正向迭代器,但没说是哪一个的。

反向迭代器需要用正向迭代器来构造。

之后反向迭代器的++,通过调用正向迭代器的--来实现。反向迭代器的--,也通过调用正向迭代器的++实现。

cpp 复制代码
reverse_iterator<Iterator, Ref, Ptr>& operator++() {
    --it;
	return *this;
}

rbegin()rend()来表示反向迭代器。但它们其实是上传原迭代器通过反向迭代器类进行封装:

cpp 复制代码
typedef T* iterator;
typedef const T* const_iterator;

typedef reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

reverse_iterator rbegin(){
	return reverse_iterator(end() - 1);
}

reverse_iterator rend(){
	return reverse_iterator(begin() - 1);
}

const_reverse_iterator rbegin() const{
	return const_reverse_iterator(end() - 1);
}

const_reverse_iterator rend() const{
	return const_reverse_iterator(begin() - 1);
}

反向迭代器的operator*是调用正向迭代器的*,因此返回值的类型需要通过模板参数来确定。

这种实现方式的类也可以叫迭代器适配器,即反向迭代器底层用正向迭代器来适配。

适配的前提:很多功能是重叠的才能去适配。例如stacklistvectordeque的功能重叠,因此可以适配。

这个反向迭代器理论上也能适配listvectordeque以及其他支持正向迭代器的容器。

易错情况:临时对象的常属性

这里假设vector的迭代器依旧用指针代替,list的迭代器通过类模板实现。

因为临时对象的常属性,因此在生成反向迭代器对象时,常量不能--,编译器报错说只能对左值操作。

临时对象具有常属性,但这里--end()的含义不同,按理来说无论是内置类型还是自定义类型,这里生成的临时对象都具有常属性,按理来说都不能--end(),但只有内置类型迭代器的vector报错了,另一个自定义类型迭代器的list没有。

解决方法是用end()-1作为形参上传给反向迭代器。这样临时拷贝不会修改原迭代器的返回值。

此外,匿名对象也具有常属性:

cpp 复制代码
class A{
    void print(){
        cout<<"A::print()\n";
    }
};

A& r=A();//不允许
A& r=A(1);//不允许

const A& r = A(1);//允许
r.print();//具有常属性的对象可以调用非const修饰的函数,案例来说应该不可以

再比如:

cpp 复制代码
--10;//不允许
10-1;//允许

使用类似end()-1的操作都是为了拿到这个位置。

因此上传end()-1,一样能拿到这个位置的值,用这个值再去调用反向迭代器的构造函数生成反向迭代器。

库里的反向迭代器

库里采用了对称的设计,反向迭代器的rbegin就是rend

按照之前的设计,这样的迭代器会少枚举元素。

但库里的*it访问的是前一个位置:

cpp 复制代码
reference operator(*) const{
    Iterator tmp=current;
    return *--tmp;
}

例如通过rbegin访问4,先--自身再访问。

后续的模拟实现主要参考库里的实现。也不能说之前的分析没用,而是学习时可以大胆猜想,再去看看自己想的和大佬的差距在哪里。

反向迭代器需要支持的功能

总结起来就这几个功能:

  1. ++,表示正向迭代器的--
  2. --,表示正向迭代器的++
  3. operator*,表示解引用。访问迭代器指向的数据的前一个位置。
  4. operator->,表示解引用。
  5. !=,表示迭代器的不等于。
  6. ==,表示迭代器的等于。
  7. 需要使用反向迭代器的容器,类的内部加上这几句代码(T是正向迭代器指向的数据的数据类型):
cpp 复制代码
typedef reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

//反向迭代器
reverse_iterator rbegin() {
    return reverse_iterator(end());
}

reverse_iterator rend() {
    return reverse_iterator(begin());
}

const_reverse_iterator rbegin() const {
    return const_reverse_iterator(end());
}

const_reverse_iterator rend() const {
    return const_reverse_iterator(begin());
}

这里什么也没有做,而是复用了原容器的正向迭代器,用正向迭代器来模拟反向迭代器的功能。

通用反向迭代器适配器模板参考程序

反向迭代器通用模板类:

cpp 复制代码
//三个模板参数分别是
//迭代器,有效数据的引用,有效数据的地址类型
template<class Iterator, class Ref, class Ptr>
class reverse_iterator {
public:
	typedef reverse_iterator<Iterator, Ref, Ptr> self;

	reverse_iterator<Iterator, Ref, Ptr>(Iterator _it)
		:it(_it) {}

	self& operator++() {
		--it;
		return *this;
	}

	self& operator--() {
		++it;
		return *this;
	}

	self operator++(int) {
		Iterator tmp = it--;
		return self(tmp);
	}

	self operator--(int) {
		Iterator tmp = it++;
		return self(tmp);
	}

    //参考库里的反向迭代器,访问前一个位置
	Ref operator*() {
		Iterator tmp = it;
		return *(--tmp);
	}
    
    //获得数据的地址
	Ptr operator->() {
		return &(operator*());
	}

	bool operator==(const self& x) const {
		return it == x.it;
	}

	bool operator!=(const self& x) const {
		return it != x.it;
	}

private:
	Iterator it;
};

只要容器类增加反向迭代器的接口作为成员函数,并重载有++--*->==!=即可使用。

测试用的命名空间mystd.h

cpp 复制代码
#pragma once
#include<cassert>
#include<queue>
#include<iostream>
using std::ostream;
using std::istream;

namespace mystd {
    template<class T>
    void swap(T& a, T& b) {
        T tmp = a;
        a = b;
        b = tmp;
    }

    //反向迭代器类模板
    //三个模板参数分别是
    //迭代器,有效数据的引用,有效数据的地址类型
    template<class Iterator, class Ref, class Ptr>
    class reverse_iterator {
    public:
        typedef reverse_iterator<Iterator, Ref, Ptr> self;

        reverse_iterator<Iterator, Ref, Ptr>(Iterator _it)
            :it(_it) {}

        self& operator++() {
            --it;
            return *this;
        }

        self& operator--() {
            ++it;
            return *this;
        }

        self operator++(int) {
            Iterator tmp = it--;
            return self(tmp);
        }

        self operator--(int) {
            Iterator tmp = it++;
            return self(tmp);
        }

        //参考库里的反向迭代器,访问前一个位置
        Ref operator*() {
            Iterator tmp = it;
            return *(--tmp);
        }

        //获得数据的地址
        Ptr operator->() {
            return &(operator*());
        }

        bool operator==(const self& x) const {
            return it == x.it;
        }

        bool operator!=(const self& x) const {
            return it != x.it;
        }

    private:
        Iterator it;
    };

    class string {
    public:
        const static size_t npos;

        //构造函数
        string(const char* s = "") {
            //求s的长度
            size_t len = 0;
            const char* tmps = s;
            while (*tmps) {
                ++len;
                ++tmps;
            }
            //初始化长度、容量等信息
            _size = len;
            _capacity = len;
            _str = new char[_capacity + 1]{ '\0' };

            //拷贝
            tmps = s;
            char* tmps2 = _str;
            while (*tmps2++ = *tmps++);
        }

        //析构函数
        ~string() {
            delete[] _str;
            _str = nullptr;
            _size = _capacity = 0;
        }

        //返回c风格字符串的地址
        const char* c_str() const {
            return _str;
        }

        //用[]进行索引访问
        char& operator[](size_t pos) {
            assert(pos < _size);
            return _str[pos];
        }
        const char& operator[](size_t pos) const {
            assert(pos < _size);
            return _str[pos];
        }

        //返回当前字符串的长度
        size_t size()const {
            return _size;
        }

        //返回容量
        size_t capacity()const {
            return _capacity;
        }

        //迭代器
        typedef char* iterator;
        typedef const char* const_iterator;
        //模板参数的类型要对齐,
        //例如const_iterator要对应const_reverse_iterator,
        //则模板参数的迭代器要上传const_iterator
        typedef mystd::reverse_iterator<iterator, char&, char*> reverse_iterator;
        typedef mystd::reverse_iterator<const_iterator, const char&, const char*> const_reverse_iterator;

        iterator begin() {
            return _str;
        }

        iterator end() {
            return _str + _size;
        }

        const_iterator begin() const {
            return _str;
        }

        const_iterator end() const {
            return _str + _size;
        }


        //反向迭代器
        reverse_iterator rbegin() {
            return reverse_iterator(end());
        }

        reverse_iterator rend() {
            return reverse_iterator(begin());
        }

        const_reverse_iterator rbegin() const {
            return const_reverse_iterator(end());
        }

        const_reverse_iterator rend() const {
            return const_reverse_iterator(begin());
        }

        //交换,独立于namespace std中的swap
        void swap(string& a) {
            //两个对象:*this,a
            mystd::swap(_str, a._str);
            mystd::swap(_size, a._size);
            mystd::swap(_capacity, a._capacity);
        }

        //拷贝构造函数
        string(const string& str)
            :_str(nullptr)//临时对象不经过构造函数会产生随机数
            , _size(0)
            , _capacity(0) {
            string tmp(str._str);//生成第2个临时对象
            mystd::string::swap(tmp);
        }

        //赋值重载:
        string& operator=(string tmp) {
            mystd::string::swap(tmp);
            return *this;
        }
        string& operator=(char c) {
            char ch[2] = { c,'\0' };
            string tmp(ch);
            mystd::string::swap(tmp);
            return *this;
        }


        //扩容
        void reserve(size_t n = 0) {
            if (n > _capacity) {
                char* tmp = new char[n + 1]{ '\0' };
                char* aa = tmp, * bb = _str;
                while (*aa++ = *bb++);
                delete[]_str;
                _str = tmp;

                _capacity = n;
            }
        }

        void resize(size_t n, char ch = '\0') {
            if (n <= _size) {
                _str[n] = '\0';
                _size = n;
                while (n < _capacity)
                    _str[n++] = '\0';
                return;
            }
            reserve(n);
            while (_size < n) {
                _str[_size] = ch;
                ++_size;
            }
        }

        //插入
        string& insert(size_t pos, const string& s) {
            assert(pos <= _size);
            reserve(_size + s._size);

            size_t end = _size - 1;
            while (end >= pos && end != -1) {
                _str[end + s._size] = _str[end];
                --end;
            }

            for (size_t i = 0; i < s._size; i++) {
                _str[pos + i] = s[i];
            }
            _size += s._size;
            return *this;
        }

        //尾插
        string& operator+=(const string& s) {
            insert(_size, s);
            _str[_size] = '\0';
            return *this;
        }

        string& operator+=(char s) {
            push_back(s);
            return *this;
        }

        void push_back(char c) {
            char ch[2] = { c,'\0' };
            insert(_size, ch);
        }

        //比较运算符重载
        bool operator==(const string& s) const {
            if (_size != s._size)
                return 0;
            for (size_t i = 0; i < s._size; i++) {
                if (_str[i] != s._str[i]) {
                    return 0;
                }
            }
            return 1;
        }

        bool operator<(const string& s) const {
            for (size_t i = 0; i < s._size && i < _size; i++) {
                if (_str[i] > s._str[i]) {
                    return 0;
                }
            }
            if (_size > s._size)
                return 0;
            return 1;
        }

        bool operator>(const string& s) const {
            return !(*this == s || *this < s);
        }
        bool operator>=(const string& s) const {
            return !(*this < s);
        }
        bool operator<=(const string& s) const {
            return !(*this > s);
        }
        bool operator!=(const string& s) const {
            return !(*this == s);
        }

        //删除
        string& erase(size_t pos = 0, size_t len = npos) {
            assert(pos < _size);
            if (len == npos || pos + len >= _size) {
                _str[pos] = '\0';
                _size = pos;
                return *this;
            }
            while (pos + len < _size) {
                _str[pos] = _str[pos + len];
                ++pos;
            }
            _str[pos] = '\0';
            _size -= len;
            return *this;
        }

        //清空
        void clear() {
            _str[0] = '\0';
            _size = 0;
        }

        //查找
        size_t find(const string& s, size_t pos = 0)const {
            for (size_t i = 0, ti; i <= _size - s._size; i++) {
                ti = i;
                for (size_t j = 0; j < s._size; j++) {
                    if (s[j] == _str[ti])
                        ++ti;
                    else
                        break;
                }
                if (ti == i + s._size)
                    return i;
            }
            return npos;
        }
        size_t find(char c, size_t pos = 0)const {
            for (size_t i = 0; i < _size; i++) {
                if (_str[i] == c)
                    return i;
            }
            return npos;
        }

        //提取片段
        string substr(size_t pos = 0, size_t len = npos)const {
            string tmp;
            if (len == npos || pos + len > _size) {
                while (tmp += _str[pos++], pos < _size);
                return tmp;
            }

            while (tmp += _str[pos++], tmp._size < len);
            return tmp;
        }

    private:
        char* _str;
        size_t _size;
        size_t _capacity;
    };
    const size_t string::npos = -1;
    ostream& operator<<(ostream& out, const string& st) {
        for (const auto& x : st)
            out << x;
        return out;
    }
    istream& operator>>(istream& in, string& s) {
        s.clear();

        char buff[129];
        size_t i = 0;

        char ch;
        //连同空格一起接收
        while (ch = in.get(), ch != ' ' && ch != '\n') {
            buff[i++] = ch;
            if (i == 128) {
                buff[i] = '\0';
                s += buff;
                i = 0;
            }
        }

        if (i != 0) {
            buff[i] = '\0';
            s += buff;
        }

        return in;
    }

    template<class T>
    class vector {
    public:

        //构造函数
        vector<T>()
            :_start(nullptr)
            , _finish(nullptr)
            , _endofstorage(nullptr)
        {}

        vector<T>(size_t n, const T& val = T())
            : _start(nullptr)
            , _finish(nullptr)
            , _endofstorage(nullptr) {
            reserve(n);
            _finish = _start + n;
            for (size_t i = 0; i < n; i++) {
                _start[i] = val;
            }
        }

        //析构函数
        ~vector<T>() {
            delete[]_start;
            _start = _finish = _endofstorage = nullptr;
        }

        //获取容量信息
        size_t capacity() const {
            return _endofstorage - _start;
        }

        //获取数量
        size_t size() const {
            return _finish - _start;
        }

        //扩容
        void reserve(size_t n) {
            while (n > capacity()) {
                size_t sz = size();
                size_t new_c = capacity();
                new_c = new_c == 0 ? n : new_c * 2;

                T* tmp = new T[new_c]{ T() };
                if (_start != nullptr) {
                    for (size_t i = 0; i < sz; i++) {
                        tmp[i] = _start[i];
                    }
                }

                _start = tmp;
                _finish = tmp + sz;
                _endofstorage = tmp + new_c;
            }
        }

        void resize(size_t n, const T& val) {
            reserve(n);
            for (size_t i = size(); i < n; i++)
                _start[i] = val;
            _finish = _start + n;
        }

        //访问
        T& operator[](size_t pos) {
            assert(pos < size());
            return _start[pos];
        }
        const T& operator[](size_t pos) const {
            assert(pos < size());
            return _start[pos];
        }

        //迭代器
        typedef T* iterator;
        typedef const T* const_iterator;
        typedef mystd::reverse_iterator<iterator, T&, T*> reverse_iterator;
        typedef mystd::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

        iterator begin() {
            return _start;
        }

        iterator end() {
            return _finish;
        }

        const_iterator begin() const {
            return _start;
        }

        const_iterator end() const {
            return _finish;
        }

        //反向迭代器
        reverse_iterator rbegin() {
            return reverse_iterator(end());
        }

        reverse_iterator rend() {
            return reverse_iterator(begin());
        }

        const_reverse_iterator rbegin() const {
            return const_reverse_iterator(end());
        }

        const_reverse_iterator rend() const {
            return const_reverse_iterator(begin());
        }

        //插入
        //单个元素
        iterator insert(iterator pos, const T& val) {
            assert(pos >= begin());
            assert(pos <= end());
            size_t sz = pos - begin();//计算偏移量
            reserve(size() + 1);
            pos = begin() + sz;

            auto End = end();
            while (End > pos) {
                *End = *(End - 1);
                --End;
            }
            *End = val;
            _finish++;
            return pos;
        }


        //尾插
        void push_back(const T& val) {
            insert(end(), val);
        }

        //删除
        //删除指定迭代器
        iterator erase(iterator pos) {
            assert(pos >= begin());
            assert(pos < end());
            auto tmp = pos;
            while (tmp < _finish) {
                *tmp = *(tmp + 1);
                ++tmp;
            }
            --_finish;
            return pos;
        }

        //删除区域的迭代器
        //左闭右开
        iterator erase(iterator Begin, iterator End) {
            assert(Begin >= begin());
            assert(End <= end());
            assert(Begin <= End);

            size_t sz = size_t(End - Begin);
            iterator tmp = Begin;
            while (tmp + sz < end()) {
                *tmp = *(tmp + sz);
                ++tmp;
            }
            _finish = tmp;
            return Begin;
        }

        //尾删
        void pop_back() {
            erase(end() - 1);
        }

        //拷贝构造
        vector<T>(const vector<T>& a)
            :_start(nullptr)
            , _finish(nullptr)
            , _endofstorage(nullptr) {
            reserve(capacity());
            for (auto& x : a)
                push_back(x);
        }

        //交换
        void swap(vector<T>& b) {
            vector<T>& a = *this;
            mystd::swap(a._start, b._start);
            mystd::swap(a._finish, b._finish);
            mystd::swap(a._endofstorage, b._endofstorage);

        }

        //赋值重载
        vector<T>& operator=(vector<T> tmp) {
            swap(tmp);
            return *this;
        }

    private:
        iterator _start;
        iterator _finish;
        iterator _endofstorage;
    };

    template<class T>
    struct __list_node {
        //指针域
        typedef __list_node* pointer;
        pointer next;
        pointer view;
        //数据域
        T data;
        __list_node(const T& x = T())
            :data(x)
            , next(nullptr)
            , view(nullptr) {}
    };

    //list专用迭代器类模板
    //三个模板参数分别为:存储的数据类型
    //存储的数据的引用、存储的数据空间的地址类型
    template<class T, class Ref, class Ptr>
    struct __list_iterator {
        typedef __list_iterator<T, Ref, Ptr> self;
        typedef __list_node<T>* link_node;

        link_node node;

        __list_iterator<T, Ref, Ptr>(link_node x = nullptr)
            :node(x) {}

        __list_iterator<T, Ref, Ptr>(const self& x)
            : node(x.node) {}

        Ref operator*() {
            return node->data;
        }

        //为了支持T为自定义类型的情况
        //返回迭代器指向的结点的数据域的地址
        Ptr operator->() {
            return &node->data;
        }

        bool operator==(const self& x) const {
            return node == x.node;
        }

        bool operator!=(const self& x) const {
            return node != x.node;
        }

        self& operator++() {
            node = node->next;
            return *this;
        }

        self& operator--() {
            node = node->view;
            return *this;
        }

        self operator++(int) {
            self tmp(*this);
            node = node->next;
            return tmp;
        }

        self operator--(int) {
            self tmp(*this);
            node = node->view;
            return tmp;
        }

    };

    template<class T>
    class list {
    public:
        typedef __list_node<T> Node;

        //默认构造函数
        list<T>() {
            node = get_node();
            node->next = node->view = node;
            _size = 0;
        }

        //构造函数
        list<T>(int n, const T& val = T()) {
            node = get_node();
            node->next = node->view = node;
            size_t tmp = n;
            for (size_t i = 0; i < tmp; i++)
                push_back(val);
        }

        list<T>(size_t n, const T& val = T()) {
            node = get_node();
            node->next = node->view = node;
            size_t tmp = n;
            for (size_t i = 0; i < tmp; i++)
                push_back(val);
        }

        template<class Inputiterator>
        list<T>(Inputiterator first, Inputiterator second) {
            node = get_node();
            node->next = node->view = node;
            while (first != second) {
                push_back(*first);
                first++;
            }
        }

        //拷贝构造函数
        list<T>(const list<T>& obj) {
            node = get_node();
            node->next = node->view = node;
            for (const auto& x : obj)
                this->push_back(x);
        }

        //赋值重载
        list<T>& operator=(list<T>obj) {
            mystd::swap(this->node, obj.node);
            mystd::swap(this->_size, obj._size);
            return *this;
        }

        //析构函数
        ~list() {
            clear();
            delete node;
        }

        //迭代器
        typedef __list_iterator<T, T&, T*> iterator;
        typedef __list_iterator<T, const T&, const T*> const_iterator;
        typedef mystd::reverse_iterator<iterator, T&, T*> reverse_iterator;
        typedef mystd::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

        iterator begin() {
            return iterator(node->next);
        }

        iterator end() {
            return iterator(node);
        }

        const_iterator begin() const {
            return const_iterator(node->next);
        }

        const_iterator end() const {
            return const_iterator(node);
        }

        //反向迭代器
        reverse_iterator rbegin() {
            return reverse_iterator(end());
        }

        reverse_iterator rend() {
            return reverse_iterator(begin());
        }

        const_reverse_iterator rbegin() const {
            return const_reverse_iterator(end());
        }

        const_reverse_iterator rend() const {
            return const_reverse_iterator(begin());
        }

        //结点数
        size_t size()const {
            return _size;
        }

        //判断是否为空
        bool empty()const {
            return this->node->next == this->node
                && this->node->view == this->node;
        }

        //头插
        void push_front(const T& val) {
            insert(begin(), val);
        }

        //尾插
        void push_back(const T& val) {
            insert(end(), val);
        }

        //尾删
        void pop_back() {
            erase(--end());
        }

        //头删
        void pop_front() {
            erase(begin());
        }

        //插入
        iterator insert(iterator pos, const T& val) {
            Node* cur = pos.node->view;
            Node* newnode = get_node(val);

            newnode->next = cur->next;
            newnode->view = cur;

            cur->next = newnode;
            newnode->next->view = newnode;

            ++_size;
            return iterator(newnode);
        }

        //删除
        iterator erase(iterator pos) {
            assert(pos != end());
            Node* del = pos.node, * cur = pos.node->next;
            del->view->next = del->next;
            del->next->view = del->view;

            delete del;
            --_size;
            return iterator(cur);
        }

        //清空
        void clear() {
            auto it = begin();
            while (it != end()) {
                it = erase(it);
            }
        }

        //访问
        T& front() {
            return node->next->data;
        }

        T& back() {
            return node->view->data;
        }
    private:
        Node* get_node(const T& x = T()) {
            Node* tmp = new Node(x);
            tmp->next = tmp->view = nullptr;
            return tmp;
        }

        template<class Type>
        friend void mystd::swap(Type&, Type&);

        Node* node;//哨兵卫
        size_t _size;//结点数
    };

    //stack和queue都是容器适配器,即靠适配器和容器组合生成的STL工具,
    //这里是部分模拟实现。
    template <class T, class Sequence = deque<T> >
    class stack {
        //...
        //省略若干库中的友元函数
    public:
        //...
        //省略若干库中没必要的typedef
    protected:
        Sequence c;
    public:
        bool empty() const { return c.empty(); }
        size_t size() const { return c.size(); }
        T& top() { return c.back(); }
        const T& top() const { return c.back(); }
        void push(const T& x) { c.push_back(x); }
        void pop() { c.pop_back(); }
    };

    template <class T, class Sequence = deque<T> >
    class queue {
        //...
        //省略若干友元函数
    public:
        //...
        //省略若干不重要的typedef
    protected:
        Sequence c;
    public:
        bool empty() const { return c.empty(); }
        size_t size() const { return c.size(); }
        T& front() { return c.front(); }
        const T& front() const { return c.front(); }
        T& back() { return c.back(); }
        const T& back() const { return c.back(); }
        void push(const T& x) { c.push_back(x); }
        void pop() { c.pop_front(); }
    };
}
相关推荐
刚入门的大一新生5 分钟前
C++初阶-string类的模拟实现与改进
开发语言·c++
小冯的编程学习之路29 分钟前
【软件测试】:推荐一些接口与自动化测试学习练习网站(API测试与自动化学习全攻略)
c++·selenium·测试工具·jmeter·自动化·测试用例·postman
C++ 老炮儿的技术栈2 小时前
什么是函数重载?为什么 C 不支持函数重载,而 C++能支持函数重载?
c语言·开发语言·c++·qt·算法
猪八戒1.02 小时前
C++ 回调函数和Lambda表达式
c++
源远流长jerry2 小时前
匿名函数lambda、STL与正则表达式
c++
tan180°3 小时前
Linux进程信号处理(26)
linux·c++·vscode·后端·信号处理
一只鱼^_4 小时前
牛客练习赛138(首篇万字题解???)
数据结构·c++·算法·贪心算法·动态规划·广度优先·图搜索算法
李匠20244 小时前
C++GO语言微服务之Dockerfile && docker-compose②
c++·容器
2301_803554525 小时前
c++和c的不同
java·c语言·c++