(1) 宏定义 Q_QDOC :
++同样 宏 Q_CLANG_QDOC 似乎也没有被定义 :
(2) 阅读 QLsit 的源码,并补充了一些注释 :
template <typename T>
class QList
#ifndef Q_QDOC // 是有继承的,下略去这样的宏定义
: public QListSpecialMethods<T>
#endif
{
using Data = QTypedArrayData<T>;
using DataOps = QArrayDataOps<T>;
using DataPointer = QArrayDataPointer<T>;
class DisableRValueRefs {};
DataPointer d; //貌似定义了指向链表中元素的指针
template <typename V, typename U> // 声明了两个友元函数
friend qsizetype QtPrivate::indexOf(const QList<V> &list,
const U &u, qsizetype from) noexcept;
template <typename V, typename U>
friend qsizetype QtPrivate::lastIndexOf(const QList<V> &list,
const U &u, qsizetype from) noexcept;
public:
using Type = T;
using value_type = T;
using pointer = T *;
using const_pointer = const T *;
using reference = T &;
using const_reference = const T &;
//using qsizetype = QIntegerForSizeof<std::size_t>::Signed;
using size_type = qsizetype; //总之是有符号类型的整数
using difference_type = qptrdiff;
//typedef QIntegerForSizeof<void *>::Signed qptrdiff;
//typedef qptrdiff qintptr;
using parameter_type = typename DataPointer::parameter_type;
//std::conditional<bool, A, B>::type
//若 bool 为真,则 type = 类型A,否则 type = 类型B
using rvalue_ref = typename std::conditional<
DataPointer::pass_parameter_by_value,
DisableRValueRefs,
T &&
>::type;
class iterator //内部类
{
T * i = nullptr; //裸指针,作为本类中的数据成员
public:
using difference_type = qsizetype;
using value_type = T;
//libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346
//gcc<11 附带的 libstdc++ 没有修复缺陷 LWG 3346
#if __cplusplus >= 202002L && //肯定是高版本 c++,选择 if 分支
(!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11)
using iterator_category = std::contiguous_iterator_tag;
using element_type = value_type;
#else
using iterator_category = std::random_access_iterator_tag;
#endif
using pointer = T *;
using reference = T &;
inline constexpr iterator() = default;
inline iterator(T * n) : i(n) {} //迭代器的有参构造函数
inline T & operator* () const { return *i; } //运算符重载
inline T * operator->() const { return i; } // *p 与 p->
inline T &operator[](qsizetype j) const
{ return *(i + j); } // i 是本迭代器类的数据成员 T * i = nullptr;
inline constexpr bool operator==(iterator o) const
{ return i == o.i; } //这里出现了 == 的成员函数重载
inline constexpr bool operator==(pointer p) const
{ return i == p; } //说明形参可以是迭代器类型或裸指针类型,均可
inline constexpr bool operator!=(iterator o) const
{ return i != o.i; }
inline constexpr bool operator!=(pointer p) const
{ return i != p; } //只对 == != 做了重载定义
//下面的运算符函数只接受迭代器类型的形参
inline constexpr bool operator<(iterator other) const
{ return i < other.i; }
inline constexpr bool operator<=(iterator other) const
{ return i <= other.i; }
inline constexpr bool operator>(iterator other) const
{ return i > other.i; }
inline constexpr bool operator>=(iterator other) const
{ return i >= other.i; }
inline iterator & operator++() { ++i; return *this; }
inline iterator operator++(int) // a++ 与 ++a
{ T *n = i; ++i; return n; }
inline iterator & operator--() { i--; return *this; }
inline iterator operator--(int) // a-- 与 --a
{ T *n = i; i--; return n; }
inline qsizetype operator-(iterator j) const
{ return i - j.i; } //俩迭代器相减
inline operator T*() const //类型转换运算符
{ return i; } // 可以隐式转换为裸指针 T* 类型
//c++14,std::enable_if_t<bool, T>
//当 bool为 true时返回 T类型,否则什么也不返回而导致编译错误
template <typename Int> //太长而换行,下面的是函数返回值
std::enable_if_t<std::is_integral_v<Int>, iterator> &
operator+=(Int j) //意思是要求模板参数 Int 是某个整数类型
{ i+=j; return *this; }
template <typename Int>
std::enable_if_t<std::is_integral_v<Int>, iterator> &
operator-=(Int j) //复合运算符 += -=
{ i-=j; return *this; }
template <typename Int> // iter + 3
std::enable_if_t<std::is_integral_v<Int>, iterator>
operator+(Int j) const
{ return iterator(i+j); }
template <typename Int> // iter - 3
std::enable_if_t<std::is_integral_v<Int>, iterator>
operator-(Int j) const
{ return iterator(i-j); }
template <typename Int> //定义了全局友元函数 3 + iter
friend std::enable_if_t<std::is_integral_v<Int>, iterator>
operator+(Int j, iterator k)
{ return k + j; }
};
class const_iterator //配套于本 Qt 容器的常量迭代器
{
const T * i = nullptr;
public:
using difference_type = qsizetype;
using value_type = T;
using iterator_category = std::contiguous_iterator_tag;
using element_type = const value_type;
using pointer = const T *;
using reference = const T &;
inline constexpr const_iterator() = default;//默认无参构造函数
inline const_iterator(const T * n) : i(n) {}//有参构造函数
inline constexpr const_iterator(iterator o): i(o) {}//有参构造
inline const T &operator*() const { return *i; } // *iter
inline const T *operator->() const { return i; } // iter->
inline const T & operator[](qsizetype j) const // iter[3]
{ return *(i + j); }
inline constexpr bool operator==(const_iterator o) const
{ return i == o.i; }
inline constexpr bool operator==( iterator o) const
{ return i == const_iterator(o).i; } // ==运算符函数的重载
inline constexpr bool operator==( pointer p) const
{ return i == p; }
inline constexpr bool operator!=(const_iterator o) const
{ return i != o.i; }
inline constexpr bool operator!=( iterator o) const
{ return i != const_iterator(o).i; }
inline constexpr bool operator!=( pointer p) const
{ return i != p; }
inline constexpr bool operator<(const_iterator other) const
{ return i < other.i; }
inline constexpr bool operator<=(const_iterator other) const
{ return i <= other.i; }
inline constexpr bool operator>(const_iterator other) const
{ return i > other.i; }
inline constexpr bool operator>=(const_iterator other) const
{ return i >= other.i; }
inline const_iterator & operator++() // a++ 与 ++a
{ ++i; return *this; }
inline const_iterator operator++(int)
{ const T *n = i; ++i; return n; }
inline const_iterator & operator--() // a-- 与 --a
{ i--; return *this; }
inline const_iterator operator--(int)
{ const T *n = i; i--; return n; }
inline qsizetype operator-(const_iterator j) const
{ return i - j.i; } // iterA - iterB
inline operator const T*() const //类型转换运算符
{ return i; } //转换为 const T*
template <typename Int> // iter += 3
std::enable_if_t<std::is_integral_v<Int>, const_iterator> &
operator+=(Int j) { i+=j; return *this; }
template <typename Int> // iter = 3
std::enable_if_t<std::is_integral_v<Int>, const_iterator>
operator+(Int j) const { return const_iterator(i+j); }
template <typename Int> // iter -= 3
std::enable_if_t<std::is_integral_v<Int>, const_iterator> &
operator-=(Int j) { i-=j; return *this; }
template <typename Int> // iter - 3
std::enable_if_t<std::is_integral_v<Int>, const_iterator>
operator-(Int j) const { return const_iterator(i-j); }
template <typename Int> //全局友元函数,响应 3 + iter 运算
friend std::enable_if_t<std::is_integral_v<Int>, const_iterator>
operator+(Int j, const_iterator k)
{ return k + j; }
};
using Iterator = iterator;
using ConstIterator = const_iterator; //说明支持反向迭代
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private: //本 QList<T> 的私有成员函数
void resize_internal(qsizetype i);
bool isValidIterator(const_iterator i) const
{ const std::less<const T*> less = {};
return !less(d->end(), i) && !less(i, d->begin());
} //本函验证形参迭代器 i 的有效性,合法返回 true,非法返回 F
//比 end() 大,比 begin() 小的迭代器都是非法迭代器
public: //有参初始化函数
QList(DataPointer dd) noexcept : d(dd) { }
public:
QList() = default; //默认的无参构造函数
//构造一个初始大小为 size 元素的列表。
//这些元素使用默认构造的值进行初始化。
explicit QList(qsizetype size) : d(Data::allocate(size))
{ if (size) d->appendInitialize(size); }
//构造一个初始大小为 size 元素的列表。每个元素都初始化为 value。
QList(qsizetype size, parameter_type t)
: d(Data::allocate(size))
{ if (size) d->copyAppend(size, t); }
//初始化列表形式的构造初始化
//QList<int> myList{1,2,3,4}
inline QList(std::initializer_list<T> args)
: d(Data::allocate( args.size() ) )
{ //从args提供的 std::initializer list构造列表。
if (args.size())
d->copyAppend(args.begin(), args.end());
}
//赋值运算符函数 myList = {1,2,3,4}
QList<T> & operator=(std::initializer_list<T> args)
{
d = DataPointer(Data::allocate(args.size()));
if (args.size())
d->copyAppend(args.begin(), args.end());
return *this;
}
template <typename InputIterator,
QtPrivate::IfIsInputIterator<InputIterator> = true>
QList(InputIterator i1, InputIterator i2)
{ //意思是接受形参俩迭代器之间的范围赋值形式的构造初始化
if constexpr (!std::is_convertible_v<
typename std::iterator_traits<InputIterator>::iterator_category,
std::forward_iterator_tag>)
{ std::copy(i1, i2, std::back_inserter(*this)); }
else { // else 系列更简单
const auto distance = std::distance(i1, i2);
if (distance) {
d = DataPointer(Data::allocate(distance));
if constexpr (
std::is_same_v<std::decay_t<InputIterator>, iterator> ||
std::is_same_v<std::decay_t<InputIterator>, const_iterator>)
{
d->copyAppend(i1, i2);
}
else {
d->appendIteratorRange(i1, i2);
}
}
}
}
// This constructor is here for compatibility with QStringList in Qt 5,
//that has a QStringList(const QString &) constructor
template<typename String, //特应用于 String 或 QString 类型
typename = std::enable_if_t<
std::is_same_v<T, QString> &&
std::is_convertible_v<String, QString>>>
inline explicit QList(const String &str)
{ append(str); }
// compiler-generated special member functions are fine!
void swap(QList &other) noexcept { d.swap(other.d); }
template <typename U = T> // == 运算符函数,比较俩链表
QTypeTraits::compare_eq_result_container<QList, U>
operator==(const QList & other) const
{
if (size() != other.size()) return false;
//只要链表的首地址相同就返回 true
if (begin() == other.begin()) return true;
// do element-by-element comparison 全链表范围的元素比较
return d->compare(begin(), other.begin(), size());
}
template <typename U = T> // != 运算符函数,比较俩链表
QTypeTraits::compare_eq_result_container<QList, U>
operator!=(const QList &other) const
{ return !(*this == other); } //基于 == 运算符完成本函
//如果此列表在词法上小于其他列表,则返回 true;否则返回 false。
//此函数要求值类型具有运算符<()的实现。lexically less than
template <typename U = T> // < 运算符函数,比较俩链表
QTypeTraits::compare_lt_result_container<QList, U>
operator<(const QList &other) const //不用在意下面的 noexcept()判断
noexcept(noexcept(std::lexicographical_compare<typename QList<U>::const_iterator,
typename QList::const_iterator>( std::declval<QList<U>>().begin(),
std::declval<QList<U>>().end(), other.begin(), other.end())))
{ return std::lexicographical_compare(
begin(), end(), other.begin(), other.end());
}
template <typename U = T> // > 运算符函数,比较俩链表
QTypeTraits::compare_lt_result_container<QList, U>
operator>(const QList &other) const
noexcept(noexcept(other < std::declval<QList<U>>()))
{
return other < *this; // 基于 < 运算符函数的实现完成 > 的函数实现
}
template <typename U = T> // <= 运算符函数,比较俩链表
QTypeTraits::compare_lt_result_container<QList, U>
operator<=(const QList &other) const
noexcept(noexcept(other < std::declval<QList<U>>()))
{
return !(other < *this); //就是不大于
}
template <typename U = T> // >= 运算符函数,比较俩链表
QTypeTraits::compare_lt_result_container<QList, U>
operator>=(const QList &other) const
noexcept(noexcept(std::declval<QList<U>>() < other))
{
return !(*this < other); //就是不小于
}
qsizetype size() const noexcept //返回链表中的元素数量
{ return d->size; }
qsizetype count() const noexcept //可见本函数等价于 size()
{ return size(); }
qsizetype length() const noexcept //可见本函数等价于 size()
{ return size(); }
inline bool isEmpty() const noexcept
{ return d->size == 0; }
//将列表的大小设置为size。如果size大于当前大小,则将元素添加到末尾;
//新元素初始化为默认构造的值。如果size小于当前大小,则从末尾删除元素。
//自Ot5.6以来,resize()不再缩小容量。要释放多余容量,请使用squeeze()。
void resize(qsizetype size) // squeeze 挤压
{ resize_internal(size);
if (size > this->size()) d->appendInitialize(size);
}
void resize(qsizetype size, parameter_type c)
{ resize_internal(size); // 为找到此函数的官方注释
if (size > this->size())
d->copyAppend(size - this->size(), c);
}
//返回在不强制重新分配的情况下可以存储在列表中的最大项数。
//此函数的唯一目的是提供微调OList内存使用的方法。
//通常,您很少需要调用此函数。如果您想知道列表中有多少项,请调用size()
inline qsizetype capacity() const
{ return qsizetype(d->constAllocatedCapacity()); }
//尝试为至少 size 个元素分配内存。
//如果你提前知道列表的大小,你应该调用这个函数来防止重新分配和内存碎片化。
//如果你经常调整列表的大小,你可能会得到更好的性能。
//如果不确定需要多少空间,通常最好用一个上界作为大小,
//或者对最可能的大小作一个高估计,如果严格的上界比这个大得多的话。
//如果规模被低估,一旦超出预留的规模,列表将根据需要增长,
//这可能导致分配比最佳高估的规模更大,并减缓触发该分配的操作。
//警告:reserve:()保留内存但不改变列表的大小。
//访问当前列表末尾以外的数据是不定义的行为。
//如果您需要访问当前列表末尾以外的内存,请使用resize()
void reserve(qsizetype size);
//Releases any memory not required to store the items.
//此函数的唯一目的是提供微调OList内存使用的方法。
//通常,您很少需要调用此函数。
inline void squeeze();
void detach() //停止共享,为写链表做准备。本函会被自动调用
{ d.detach(); } //判断是否停止了链表共享,是则返回 true
bool isDetached() const noexcept { return !d->isShared(); }
inline bool isSharedWith(const QList<T> &other) const
{ return d == other.d; } //判断这俩链表是否在共享元素
//返回存储在列表中的数据的指针。该指针可用于访问和修改列表中的项。
//警告:在分离或修改 QList 时,指针会被无效化。
//这个函数主要用来将一个列表传递给一个接受纯 C++数组的函数。
pointer data() { detach(); return d->data(); }
// QList<int> list(10); int *data = list.data();
// for (qsizetype i = 0; i < 10; ++i) data[i] = 2 * i;
//本函数可见, QT6 里的Qlist 已经弱化为 vector
//只有数组才可以直接使用地址的加减法运算 了
const_pointer data() const noexcept
{ return d->data(); } //一模一样,只是为了方便常量对象
const_pointer constData() const noexcept
{ return d->data(); }
//从列表中删除所有元素。
//注意:在Qt5.6之前,这也会释放列表使用的内存。
//从Qt5.7开始,容量被保留。
//要清除所有容量,请使用默认构造的列表进行交换: 举例在此处略了
void clear() //清除链表中的所有元素
{ if (!size()) return;
if (d->needsDetach()) {
// must allocate memory
DataPointer detached(Data::allocate(d.allocatedCapacity()));
d.swap(detached);
} else {
d->truncate(0);
}
}
const_reference at(qsizetype i) const noexcept
{ Q_ASSERT_X(size_t(i) < size_t(d->size),
"QList::at", "index out of range");
return data()[i];
}
//QList<T>.at(3) 与 QList<T>.[3] 返回的都是左值引用
reference operator[](qsizetype i)
{
Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::operator[]", "index out of range");
detach();
return data()[i];
}
const_reference operator[](qsizetype i) const noexcept
{ return at(i); }
void append(parameter_type t) //在链表末尾添加数据
{ emplaceBack(t); }
//把迭代器 i1 到 i2 之间的数据都添加进来
void append(const_iterator i1, const_iterator i2);
void append(rvalue_ref t) //形参是右值引用
{ if constexpr (DataPointer::pass_parameter_by_value) {
Q_UNUSED(t);
} else {
emplaceBack(std::move(t));
}
}
void append(const QList<T> &l) //把形参链表中的数据都复制过来
{ append(l.constBegin(), l.constEnd()); }
void append(QList<T> &&l); //把形参链表中的数据都移动过来
void prepend(parameter_type t) { emplaceFront(t); }
//通常情况下,这种操作相对较快(摊销常数时间)。
//(QList能够在列表数据开始时分配额外的内存,并在每次操作时按该方向增长,
//而无需重新分配或移动数据。但是,如果您想要一个具有常数时间前缀保证的容器类,
//请使用std::ist,否则请使用QList。
void prepend(rvalue_ref t) //移动版本
{
if constexpr (DataPointer::pass_parameter_by_value) {
Q_UNUSED(t);
} else {
emplaceFront(std::move(t)); //move 右值引用
}
}
template<typename... Args> //万能引用版本,尾部插入
inline reference emplaceBack(Args &&... args);
//返回值应该是左值引用。一般也不会关心返回值
//using reference = T &;
template <typename ...Args> //万能引用版本,头部插入
inline reference emplaceFront(Args&&... args);
//对于大型列表,此操作可能很慢(线性时间),
//因为它需要将索引为 i及之后的所有项在内存中移动一位。
//如果您想要一个提供快速插入功能的容器类,请使用std::list。
//此注释实锤了 QList<T> 就是适量数组 vector,而非指针链表 std::list
//Inserts value at index position i in the list.
iterator insert(qsizetype i, parameter_type t)
{ return emplace(i, t); } //任意位置插入
//Inserts n copies of t at index position i in the list.
iterator insert(qsizetype i, qsizetype n, parameter_type t);
//将值插入迭代器 before指向的项前面。返回指向插入项的迭代器。
iterator insert(const_iterator before, parameter_type t)
{
Q_ASSERT_X(isValidIterator(before),
"QList::insert",
"The specified iterator argument 'before' is invalid");
return insert(before, 1, t);
}
//留意此函数的返回值,即返回的迭代器指向哪里
//Inserts n copies of t in front of the item
//pointed to by the iterator before.
//Returns an iterator pointing at the first of the inserted items.
//在迭代器 before 之前插入 n个元素。返回指向插入项的第一个的迭代器。
iterator insert(const_iterator before, qsizetype n, parameter_type t)
{
Q_ASSERT_X(isValidIterator(before),
"QList::insert",
"The specified iterator argument 'before' is invalid");
return insert(std::distance(constBegin(), before), n, t);
}
iterator insert(const_iterator before, rvalue_ref t)
{
Q_ASSERT_X(isValidIterator(before), //移动插入
"QList::insert",
"The specified iterator argument 'before' is invalid");
return insert(std::distance(constBegin(), before), std::move(t));
}
iterator insert(qsizetype i, rvalue_ref t)
{
if constexpr (DataPointer::pass_parameter_by_value) {
Q_UNUSED(i);
Q_UNUSED(t);
return end();
} else {
return emplace(i, std::move(t));
}
}
//通过在位置 before插入一个新元素来扩展容器。
//这个新元素使用 args 作为其构造的参数,直接在原地构造。
template <typename ...Args> //万能引用,args 用于定点 new新元素
iterator emplace(const_iterator before, Args&&... args)
{
Q_ASSERT_X(isValidIterator(before),
"QList::emplace",
"The specified iterator argument 'before' is invalid");
return emplace(
std::distance(constBegin(), before),
std::forward<Args>(args)...);
}
template <typename ...Args> // 贡献于插入操作
iterator emplace(qsizetype i, Args&&... args);
void replace(qsizetype i, parameter_type t)
{ //容器中元素的替换操作 arr[i] = t
Q_ASSERT_X(i >= 0 && i < d->size,
"QList<T>::replace", "index out of range");
DataPointer oldData;
d.detach(&oldData);
d.data()[i] = t;
}
void replace(qsizetype i, rvalue_ref t) //右值引用
{
if constexpr (DataPointer::pass_parameter_by_value) {
Q_UNUSED(i);
Q_UNUSED(t);
} else {
Q_ASSERT_X(i >= 0 && i < d->size,
"QList<T>::replace", "index out of range");
DataPointer oldData;
d.detach(&oldData);
d.data()[i] = std::move(t); //移动 move版本
}
}
//从列表中删除 n个元素,从索引位置 i开始。
//元素移除将保留列表的容量,不会减少分配的内存量。
//为了释放额外的容量并尽可能多地释放内存,请调用squeeze()。
//注:当 QList不是隐式共享时,此函数仅使在指定位置或之后的迭代器无效。
void remove(qsizetype i, qsizetype n = 1);
void removeFirst() noexcept; //这个好理解,头个
void removeLast () noexcept; //尾部
value_type takeFirst() //返回头部元素,并删除这个头部元素
{ Q_ASSERT(!isEmpty());
value_type v = std::move(first());
d->eraseFirst();
return v;
}
value_type takeLast() //返回尾部元素,并删除这个尾部元素
{ Q_ASSERT(!isEmpty());
value_type v = std::move(last());
d->eraseLast();
return v;
}
//Assigns value to all items in the list.
//If size is different from -1 (the default),
//the list is resized to size beforehand.
//将值分配给列表中的所有项目。
//如果大小与-1(默认值)不同,则列表将预先调整为大小。
QList<T> & fill(parameter_type t, qsizetype size = -1);
using QListSpecialMethods<T>::contains;
using QListSpecialMethods<T>::indexOf;
using QListSpecialMethods<T>::lastIndexOf;
//using qsizetype = QIntegerForSizeof<std::size_t>::Signed;
template <typename AT = T> // qsizetype 就是个有符号整数
qsizetype count(const AT & t) const noexcept
{ return qsizetype(
std::count( data(), data() + size(), t)
);
} //返回列表中值 t 出现的次数。
//此函数要求值类型具有 operator==()的实现。
void removeAt(qsizetype i) { remove(i); }
//Removes the element at index position i.
//Element removal will preserve the list's capacity
//and not reduce the amount of allocated memory.
//从列表中删除所有等于t的元素。
//如果有任何元素被删除,则返回删除的元素数量。
template <typename AT = T> //本函同样不会改变 Qlist的内存容量
qsizetype removeAll(const AT & t)
{
return QtPrivate::sequential_erase_with_copy(*this, t);
}
//从列表中删除与t比较相等的第一个元素。返回是否实际上删除了元素。
template <typename AT = T>
bool removeOne(const AT & t)
{
return QtPrivate::sequential_erase_one(*this, t);
}
//从列表中删除所有谓词 pred 返回 true 的元素。
//如果有任何元素被删除,则返回删除的元素数量。
template <typename Predicate>
qsizetype removeIf(Predicate pred)
{
return QtPrivate::sequential_erase_if(*this, pred);
}
T takeAt(qsizetype i) //删除下标 i 处的元素
{ T t = std::move((*this)[i]);
remove(i);
return t;
}
//using qsizetype = QIntegerForSizeof<std::size_t>::Signed;
//Moves the item at index position from to index position to.
void move(qsizetype from, qsizetype to) //形参是两个下标值
{ Q_ASSERT_X(from >= 0 && from < size(),
"QList::move(qsizetype, qsizetype)",
"'from' is out-of-range");
Q_ASSERT_X(to >= 0 && to < size(),
"QList::move(qsizetype, qsizetype)",
"'to' is out-of-range");
if (from == to) // don't detach when no-op
return;
detach(); //结束隐式共享,准备修改 QList 数组中的数据
T * const b = d->begin(); //获得裸指针
if (from < to)
std::rotate(b + from, b + from + 1, b + to + 1);
else
std::rotate(b + to, b + from, b + from + 1);
}
/*
template <class _FwdIt>
_CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) {
// exchange the ranges [_First, _Mid) and [_Mid, _Last)
// that is, rotates [_First, _Last) left by distance(_First, _Mid) positions
// returns the iterator pointing at *_First's new home
*/
// STL-style //看来发出迭代器时就停止了隐式共享了
iterator begin() { detach(); return d->begin(); }
iterator end () { detach(); return d->end(); }
const_iterator begin() const noexcept
{ return d->constBegin(); }
const_iterator end() const noexcept
{ return d->constEnd(); }
const_iterator cbegin() const noexcept
{ return d->constBegin(); }
const_iterator cend() const noexcept
{ return d->constEnd(); }
const_iterator constBegin() const noexcept
{ return d->constBegin(); }
const_iterator constEnd() const noexcept
{ return d->constEnd(); }
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const noexcept
{ return const_reverse_iterator(end()); }
const_reverse_iterator rend() const noexcept
{ return const_reverse_iterator(begin()); }
const_reverse_iterator crbegin() const noexcept
{ return const_reverse_iterator(end()); }
const_reverse_iterator crend() const noexcept
{ return const_reverse_iterator(begin()); }
//移除 [begin, end) 之间的所有项。
//返回一个迭代器,值与 end 相同。
iterator erase(const_iterator begin, const_iterator end);
//从列表中移除由迭代器 pos 指向的项目,
//并返回迭代器以获取列表中的下一个项目(可能是 end)
inline iterator erase(const_iterator pos)
{ return erase(pos, pos+1); }
//Removes the item pointed to by the iterator pos from the list,
//and returns an iterator to the next item in the list
//(which may be end()).
// more Qt
inline T& first() //返回头元素的左值引用
{ Q_ASSERT(!isEmpty()); return *begin(); }
inline const T & first() const noexcept
{ Q_ASSERT(!isEmpty()); return *begin(); }
inline const T &constFirst() const noexcept
{ Q_ASSERT(!isEmpty()); return *begin(); }
inline T& last() //返回对最后一个元素的左值引用
{ Q_ASSERT(!isEmpty()); return *( end() - 1); }
inline const T & last() const noexcept
{ Q_ASSERT(!isEmpty()); return *( end() - 1); }
inline const T & constLast() const noexcept
{ Q_ASSERT(!isEmpty()); return *( end() - 1); }
//判断本链表开头的元素是否是形参值
inline bool startsWith(parameter_type t) const
{ return !isEmpty() && first() == t; }
//判断本链表结尾的元素是否是形参值
inline bool endsWith(parameter_type t) const
{ return !isEmpty() && last () == t; }
QList<T> first(qsizetype n) const
{ //返回包含此列表的前 n个元素的子列表。
Q_ASSERT(size_t(n) <= size_t(size()));
return QList<T>(begin(), begin() + n);
}
//返回一个子列表,包含当前列表中从位置 pos开始的 len个元素。
//如果 leng为-1(默认值),则包含 pos之后的全部元素;
//否则,包含 len 个元素(或者少于 len个元素的所有剩余元素)。
QList<T> mid(qsizetype pos, qsizetype len = -1) const;
//返回一个子列表,包含此列表的最后 n个元素。
QList<T> last(qsizetype n) const
{ Q_ASSERT(size_t(n) <= size_t(size()));
return QList<T>(end() - n, end());
}
//返回一个子列表,该子列表包含从位置 pos 开始到列表末尾的所有元素。
QList<T> sliced(qsizetype pos) const
{
Q_ASSERT(size_t(pos) <= size_t(size()));
return QList<T>(begin() + pos, end());
}
//返回一个子列表,该子列表包含此列表的 n个元素,从位置 pos开始。
QList<T> sliced(qsizetype pos, qsizetype n) const
{
Q_ASSERT(size_t(pos) <= size_t(size()));
Q_ASSERT(n >= 0);
Q_ASSERT(pos + n <= size());
return QList<T>(begin() + pos, begin() + pos + n);
}
//如果索引 i超出范围,该函数将返回默认值。
T value(qsizetype i, parameter_type defaultValue) const;
//返回列表中索引位置/的值。如果索引i超出范围,函数将返回一个默认构造的值。
//如果您确定 i在范围内,可以使用 at()函数,它稍微快一些。
T value(qsizetype i) const { return value( i, T() ); }
void swapItemsAt(qsizetype i, qsizetype j) //交换链表中元素
{
Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(),
"QList<T>::swap", "index out of range");
detach();
qSwap(d->begin()[i], d->begin()[j]);
}
// STL compatibility
inline void push_back(parameter_type t) { append(t); }
void push_back(rvalue_ref t) { append(std::move(t)); }
void push_front(rvalue_ref t) { prepend(std::move(t)); }
inline void push_front(parameter_type t) { prepend(t); }
void pop_back() noexcept { removeLast(); }
void pop_front() noexcept { removeFirst(); }
//为容器添加一个新元素到末尾。返回新元素的引用。
//这个新元素使用 args... 作为其构造的参数在原地构建。
template <typename ...Args>
reference emplace_back(Args&&... args)
{ return emplaceBack(std::forward<Args>(args)...); }
inline bool empty() const noexcept
{ return d->size == 0; }
inline reference front() { return first(); }
inline const_reference front() const noexcept
{ return first(); }
inline reference back() { return last(); }
inline const_reference back() const noexcept
{ return last(); }
//这个函数是为了STL兼容性而提供的。它等同于squeeze()
void shrink_to_fit() { squeeze(); }
// comfort
QList<T> & operator+=(const QList<T> &l) //表连接
{ append(l); return *this; } // listA += listB
QList<T> & operator+=(QList<T> &&l) //移动的表连接
{ append(std::move(l)); return *this; }
inline QList<T> &operator+=(parameter_type t)
{ append(t); return *this; } //listA + elemB
inline QList<T> & operator+=(rvalue_ref t)
{ append(std::move(t)); return *this; }
inline QList<T> operator+(const QList<T> &l) const
{ QList n = *this; n += l; return n; } //sA + sB
inline QList<T> operator+(QList<T> &&l) const
{ QList n = *this; n += std::move(l); return n; }
inline QList<T> & operator<<(QList<T> &&l)
{ *this += std::move(l); return *this; }
inline QList<T> & operator<<(const QList<T> &l)
{ *this += l; return *this; } //listA << listB
inline QList<T> & operator<< (parameter_type t)
{ append(t); return *this; } //listA << elemB
inline QList<T> &operator<<(rvalue_ref t)
{ append(std::move(t)); return *this; }
// Consider deprecating in 6.4 or later
static QList<T> fromList(const QList<T> &list) noexcept
{ return list; }
QList<T> toList() const noexcept { return *this; }
static inline QList<T>
fromVector(const QList<T> &vector) noexcept
{ return vector; } //官方建议废弃
inline QList<T> toVector() const noexcept { return *this; }
template<qsizetype N> //奇奇怪怪,没有官方注释
static QList<T> fromReadOnlyData(const T (&t)[N]) noexcept
{
return QList<T>({ nullptr, const_cast<T *>(t), N });
}
};
#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
template <typename InputIterator,
typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
QtPrivate::IfIsInputIterator<InputIterator> = true>
QList(InputIterator, InputIterator) -> QList<ValueType>;
#endif
template <typename T> //本函数可能真的缩小了数组
inline void QList<T>::resize_internal(qsizetype newSize)
{
Q_ASSERT(newSize >= 0);
if ( d->needsDetach() ||
newSize > capacity() - d.freeSpaceAtBegin())
{
d.detachAndGrow(QArrayData::GrowsAtEnd,
newSize - d.size, nullptr, nullptr);
}
else if (newSize < size()) {
d->truncate(newSize);
}
}
//Warning: reserve() reserves memory
//but does not change the size of the list.
//自Qt5.6以来,resize()不再缩小容量。要释放多余容量,请使用squeeze()。
template <typename T> void QList<T>::reserve(qsizetype asize)
{
// capacity() == 0 for immutable data,
//so this will force a detaching below
if (asize <= capacity() - d.freeSpaceAtBegin()) {
if (d->flags() & Data::CapacityReserved)
return; // already reserved, don't shrink
if (!d->isShared()) {
// accept current allocation, don't shrink
d->setFlag(Data::CapacityReserved);
return;
}
}
DataPointer detached(Data::allocate(qMax(asize, size())));
detached->copyAppend(constBegin(), constEnd());
if (detached.d_ptr())
detached->setFlag(Data::CapacityReserved);
d.swap(detached);
}
//Releases any memory not required to store the items.
//The sole purpose of this function is to provide a means of
//fine tuning(微调) QList's memory usage.
//In general, you will rarely ever need to call this function.
template <typename T>
inline void QList<T>::squeeze()
{
if (!d.isMutable())
return;
if (d->needsDetach() || size() < capacity()) {
// must allocate memory
DataPointer detached(Data::allocate(size()));
if (size()) {
if (d.needsDetach())
detached->copyAppend(constBegin(), constEnd());
else
detached->moveAppend(d.data(), d.data() + d.size);
}
d.swap(detached);
}
// We're detached so this is fine
d->clearFlag(Data::CapacityReserved);
}
template <typename T> //范围删除:从下标 i 开始的 n 个元素
inline void QList<T>::remove(qsizetype i, qsizetype n)
{
Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(d->size),
"QList::remove", "index out of range");
Q_ASSERT_X(n >= 0, "QList::remove", "invalid count");
if (n == 0) return;
d.detach();
d->erase(d->begin() + i, n); //注意是 n 个数量
}
template <typename T>
inline void QList<T>::removeFirst() noexcept
{
Q_ASSERT(!isEmpty());
d.detach();
d->eraseFirst();
}
template <typename T>
inline void QList<T>::removeLast() noexcept
{
Q_ASSERT(!isEmpty());
d.detach();
d->eraseLast();
}
template<typename T>
inline T QList<T>:: //返回下标 i 处的元素,并提供默认值
value(qsizetype i, parameter_type defaultValue) const
{
return size_t(i) < size_t(d->size)
? at(i)
: defaultValue;
}
template <typename T>
inline void
QList<T>::append(const_iterator i1, const_iterator i2)
{
d->growAppend(i1, i2);
}
template <typename T>
inline void QList<T>::append(QList<T> &&other)
{
Q_ASSERT(&other != this);
if (other.isEmpty()) return;
if (other.d->needsDetach() ||
!std::is_nothrow_move_constructible_v<T>)
return append(other);
// due to precondition &other != this,
//we can unconditionally modify 'this'
d.detachAndGrow(QArrayData::GrowsAtEnd,
other.size(), nullptr, nullptr);
Q_ASSERT(d.freeSpaceAtEnd() >= other.size());
d->moveAppend(other.begin(), other.end());
}
//在需要频繁在列表前面插入元素时,
//emplaceFront 提供了比 prepend 更高效的插入方式。????
//void prepend(parameter_type t) { emplaceFront(t); }
template<typename T>
template<typename... Args> //在头部插入并构造元素
inline typename QList<T>::reference //返回值
QList<T>::emplaceFront(Args &&... args)
{
d->emplace(0, std::forward<Args>(args)...);
return *d.begin();
}
//#define Q_LIKELY(expr) __builtin_expect(!!(expr), true)
//提示编译器,所包围的条件 expr 很可能评估为 true。
//使用此宏可以帮助编译器对代码进行优化
template <typename T>
inline typename QList<T>::iterator
QList<T>::insert(qsizetype i, qsizetype n, parameter_type t)
{
Q_ASSERT_X(size_t(i) <= size_t(d->size),
"QList<T>::insert", "index out of range");
Q_ASSERT_X(n >= 0, "QList::insert", "invalid count");
if (Q_LIKELY(n))
d->insert(i, n, t);
return d.begin() + i;
}
//通过在位置i插入一个新元素来扩展容器。
//这个新元素使用 args 作为其构造的参数,直接在原地构造。
//返回指向新元素的迭代器。
template <typename T>
template <typename ...Args> //在下标 i 处插入并构造元素
typename QList<T>::iterator
QList<T>::emplace(qsizetype i, Args&&... args)
{
Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
d->emplace(i, std::forward<Args>(args)...);
return d.begin() + i;
}
template<typename T>
template<typename... Args> //尾部构造
inline typename QList<T>::reference //返回值
QList<T>::emplaceBack(Args &&... args)
{
d->emplace(d->size, std::forward<Args>(args)...);
return *(d.end() - 1);
}
//Removes all the items from begin up to (but not including) end.
//Returns an iterator to the same item
//that end referred to before the call.
template <typename T>
typename QList<T>::iterator
QList<T>::erase(const_iterator abegin, const_iterator aend)
{ Q_ASSERT_X(isValidIterator(abegin),
"QList::erase",
"The specified iterator argument 'abegin' is invalid");
Q_ASSERT_X(isValidIterator(aend),
"QList::erase",
"The specified iterator argument 'aend' is invalid");
Q_ASSERT(aend >= abegin);
qsizetype i = std::distance(constBegin(), abegin);
qsizetype n = std::distance(abegin, aend);
remove(i, n);
return d.begin() + i;
}
//Assigns value to all items in the list.
//If size is different from -1 (the default),
//the list is resized to size beforehand.
template <typename T>
inline QList<T> &
QList<T>::fill(parameter_type t, qsizetype newSize)
{
if (newSize == -1) newSize = size();
if (d->needsDetach() || newSize > capacity()) {
// must allocate memory
DataPointer detached(
Data::allocate(d->detachCapacity(newSize)));
detached->copyAppend(newSize, t);
d.swap(detached);
} else {
// we're detached
const T copy(t);
d->assign(d.begin(), //qMin(a, b)
d.begin() + qMin( size(), newSize),
t);
if (newSize > size()) {
d->copyAppend(newSize - size(), copy);
} else if (newSize < size()) {
d->truncate(newSize);
}
}
return *this;
}
//*********至此,终于结束容器源码 Qlist<T> = vector
(3)
谢谢