gpt4 book ai didi

c++ - 为什么 QList::at() 不检查索引是否存在并且还返回一个只读值?

转载 作者:搜寻专家 更新时间:2023-10-31 01:34:44 25 4
gpt4 key购买 nike

这个问题更多的是询问,而不是实际寻求问题的解决方案。

QList::at()不仅不检查索引是否越界,而且还返回 const因此它只能用于 read-only场景:

const T &QList::at(int i) const

Returns the item at index position i in the list. i must be a valid index position in the list (i.e., 0 <= i < size()).

This function is very fast (constant time).

我刚刚发现了 QList 的这些特殊实现细节在尝试为列表中的元素分配新值时,我想知道是否有这样做的理由。

不检查索引有效性

C++ STL如果我们取 std::arraystd::vector (我没有使用 std::list,因为它根本没有 std::list::at())我们有以下内容:

std::vector::at

The function automatically checks whether n is within the bounds of valid elements in the vector, throwing an out_of_range exception if it is not

起初我以为不包括检查以确保“此功能非常快(恒定时间)”。但是在查看了 QList 的实现之后我不得不说,即使包含检查,也肯定可以确保恒定时间(和高速)。

检查越界需要两件事(据我所知):

  • 检查给定索引是否小于 0 - 这是一个恒定时间检查(O(1) 如果我们使用一些古怪的符号)。显然我们不能有负索引(我们可以在 Python 但它有另一个含义 ;))
  • 检查给定索引是否为 < QList::size() - 这里也有常数时间 QList::size()实现是:

    inline int size() const Q_DECL_NOTHROW { return d->end - d->begin; }

    这又是O(1) (如果我没记错的话)因为这两个值都存储在 QList::d 中参数是一个指针

    struct Data {
    QtPrivate::RefCount ref;
    int alloc, begin, end;
    void *array[1];
    };

    因此访问它们并计算它们的差异不会对性能造成太大影响(显然它有一些轻微的影响,因为它引入了一些访问和算术操作以及由于 QList::size() 内的跳转而备份和恢复堆栈函数)。

那么为什么要转储索引有效性检查呢?性能影响真的那么大吗?

返回只读值

通过这样做 QList::at()函数提供了一个隐藏且(omho)不是很有用的功能,这使得使用它和QList::[]有所不同。更令人困惑。还有 C++ STL相当于 std::vectorstd::array允许使用此函数分配新值。

最佳答案

有“3”种方法可以从 QList 中的索引访问项目:

const T& QList::at(int) const
T& QList::operator[](int)
const T& QList::operator[](int) const

如果你看文档,你会看到最后一个很简单:

Same as at(). This function runs in constant time.

所以我们只剩下第一个 (at) 和非常量 operator[]。这是问题所在,第二个的文档告诉您1:

If this function is called on a list that is currently being shared, it will trigger a copy of all elements. Otherwise, this function runs in constant time. If you do not want to modify the list you should use QList::at().

注意: QVector 也是如此:

Note that using non-const operators can cause QVector to do a deep copy.

1 对于QList,这实际上只适用于Qt 5。 , 不适用于 Qt 4 (至少在文档中是这样),但是对于 QVector 它已经适用于 Qt 4 ,因此 .at 方法可能在所有 Qt 容器之间保持一致。

这意味着您不能直接在非常量共享QList 或非常量QVector 上使用operator[],您需要做类似的事情:

QList<T> &mySharedQList = ...;
const QList<T> &myConstRef = mySharedQList;
myConstRef[0]; // Only ways not to copy the original QList

我的猜测是 .at 的目的是为您提供一种保证 恒定访问时间的方法,无论 QListQVector 是(operator[] 不保证)。对于标准库容器,您不需要这样的方法,因为非 const operator[] 已经保证在恒定时间内运行(它们永远不会制作拷贝)。

关于索引检查,这可能是为了保持 operator[] 的行为,因为与 std::vector 不同,您可能想使用 .at 任何地方你只需要读取数据。

关于c++ - 为什么 QList::at() 不检查索引是否存在并且还返回一个只读值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38760274/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com