为什么要使用QVector(Qt)而不是std :: vector?

68

我对C++和Qt很陌生,但我很擅长C#/Java。

关键是我喜欢跨平台,但我对Qt感到困惑。难道 std::vector 已经支持跨平台了吗?Qt是否提供了一个非跨平台东西的等效物?

此外,FileQFile 有什么区别?

如果有链接就更好了,谢谢 :)


1
在编程中也没有任何一个与QFile相比的FileFILE *则完全不同。 - rubenvb
11
Qt很古老,提供了一些曾经并非所有编译器都可用的组件。这些组件在新代码中已经没有太多用处了。 - Bo Persson
6
补充一下 @Bo Persson 的回答:Qt 容器甚至不支持 64 位。它们使用 int 存储大小,因此在 x86-64 上无法存储超过 2^31 个元素。 - Fred Foo
1
如果我必须调用一个只接受Qt容器的函数,那么我才会使用Qt容器。 - edA-qa mort-ora-y
larsmans但是这个呢?来自Qt文档的:typedef qint64此类型为long long int(__int64在Windows上)的typedef。该类型在Qt支持的所有平台上保证为64位。 可以使用Q_INT64_C()宏创建此类型的文字:qint64 value = Q_INT64_C(932838457459459); - Tebe
1
只要类的方法/实例变量使用int类型定义,无论传递真正的64位值,你都不会获得64位的好处,因为它们将在第一个隐式转换中丢失。 - Regexident
7个回答

53

这篇文章看起来不错,它比较了Qt模板库和标准模板库:

希望您会在文章中发现所有列出的差异。

编辑:

以下是我觉得有趣的内容:

我的看法是,QTL最大的优点是,在Qt支持的所有操作系统上都具有相同的实现(包括二进制兼容性)。某些STL实现可能在性能方面不太好,或者可能缺少功能。有些平台甚至没有STL!另一方面,STL更可定制,并且在头文件中完全可用...就像他说的那样,没有明确的胜者

就像他所说的,没有明确的胜者。但是阅读这篇文章会让很多事情变得清晰。了解差异总比在不了解另一种选择的情况下选择其中之一要好。


10
从同样的观点来看,Qt 可能不够优越并且缺少功能。那么模板容器的“二进制兼容性”是什么? - edA-qa mort-ora-y
1
有人可以更新一下这个帖子吗?我是说自从这个答案发布以来已经过了一段时间了。C++11和C++14有没有为STL带来任何新的东西?C++现在不是正在努力成为跨平台吗?只是我的好奇心。 - Paul-Sebastian Manole
1
@Paul-SebastianManole:C++ 从一开始就是跨平台的。 - Nawaz
1
@Paul-SebastianManole:即使是STL从一开始就是跨平台的。 - Nawaz
1
@Nawaz 看起来 "QTL vs STL" 的链接已经失效了。 - Vincas Dargis
显示剩余5条评论

16

QVector类是引用计数的,旨在共享而不是复制。Qt提供了许多与STL容器相对应的容器。这份文档描述了这些容器及其内部结构和一些原理解释:


10

来自这里:

Qt最初诞生于一个时代,那时C++和标准库还没有被编译器充分支持或标准化。因此,它复制了很多现在已经存在于标准库中的东西,比如容器和类型信息。更重要的是,他们修改了C++语言,提供了信号(signals),以至于Qt类不能轻松地与非Qt类一起使用。


10
这并不是全部的故事,会给人留下错误的印象。仍然有使用Qt容器的理由,尤其是共享内存等方面。但如果你没有使用其他Qt组件,就不要使用它们。 - rubenvb
3
我不知道一个gtkmm常见问题解答是否是获取Qt信息的最佳来源...至少这部分声称Qt修改了C++语言的说法是不正确的。 - user362638
1
@Roku:你还有什么其他的方式来描述MOC吗? - ildjarn
1
C++语言不变 - Tebe
1
Moc是C++的预处理器,以支持元对象。它将Q_OBJECT和其他元对象宏编译成C++。因此,它们扩展了C++;就像C++扩展了“C”一样。通常您不需要了解它们,只需编写直接的C++代码即可。 - CodeLurker
我对Qt不太熟悉,但我无法理解预处理宏如何能够“修改C++语言”。此外,目前C++理论家们一致认为,在C++中不应该使用C预处理器,但许多已建立的C++库(如MFC、WxWidgets、Boost和Qt)却大量使用预处理器。 - Hilton Fernandes

2

由于没有回答提到,Qt容器,包括QVector通常具有更完整的API,这确实提供了一定程度的额外便利性,并在与std::vector相比时减少了冗余。

QVector并没有真正集成到Qt API中,这个角色被不合适的QList所取代,因此使用QVector以获得与Qt API的整体更好兼容性并不是一个强有力的论点。需要注意的是,随着对QList的缺点越来越被认可,这种情况可能会在Qt 6中发生改变。

话虽如此,如果您已经依赖于Qt进行应用程序开发,使用QVector是非常合理的选择。我想没有人会为了一个或两个容器而添加如此庞大的Qt依赖。QVector高效且性能稳定,在任何由Qt支持的平台上都可以无问题运行。

另一方面,如果您想创建一个与框架无关的核心逻辑API,最好是使用标准C++进行开发,这样您就可以获得一个不受特定GUI框架限制的可移植代码,将来如果需要,可以轻松迁移到其他GUI框架。

Qt 6 更新:现在 QListQVector 在功能上几乎完全相同

2
我通过这段代码比较了Vector和QVector,发现Vector比QVector要快得多。 这两段代码都是在Qt Creator中实现的,并且使用Visual Studio 2019编译器进行编译。
void qvectortest()
{
    QVector<double> s[10][100];
        for (int is = 0; is < 100000; is++)
        {


        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 100; j++)
            {
                for (int k = 0; k < 10000; k++)
                {
                    s[i][j].push_back(k);
                }
            }
        };
        QVector<double> d;
        d=s[0][0].mid(0);
        d.clear();
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 100; j++)
            {

                s[i][j].clear();

            };
        };
        cout << "Qvector="<<is << endl;
        }
}

并且

void vectortest()
{
    vector<double> s[10][100];
        for (int is = 0; is < 100000; is++)
        {


        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 100; j++)
            {
                for (int k = 0; k < 10000; k++)
                {
                    s[i][j].push_back(k);
                }
            }
        };
        vector<double> d;
        d.assign(s[0][0].begin(), s[0][0].end());
        d.clear();
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 100; j++)
            {

                s[i][j].clear();

            };
        };
        cout << "vector="<<is << endl;
        }
}

比较操作/时间数字


1
我曾经遇到过的关于QTL的不良经历与QTL没有引发任何异常有关;这使得追踪和修复关键错误变得更加困难。此外,STL实现与编译器密切相关,因为库的某些部分需要编译器特定的语言扩展。这意味着STL实现通常可以优于QTL,因为QTL需要可移植,因此无法从这些扩展中受益。对我来说,调试问题是至关重要的。

0

C++的std::vector是跨平台的,因为它是C++标准的一部分,每个符合C++标准的编译器都必须提供它。

我不熟悉Qt,但我在文档中看到了这个注解

注意:该类中的所有函数都是可重入的。

很可能(推测)QVector类比std::vector更容易集成以持有Qt-centric对象。再次说明,我对Qt不太熟悉,所以你必须自己决定。

作为一个经验法则(也有很多例外),除非有强烈的理由使用某些特定于库的容器类,否则我会倾向于使用std::vector


3
可重入与你的意思没有关系。可重入指任何线程都可以在同一个可重入类的实例上调用成员函数,而无需等待其他线程完成对同一类的成员函数的调用。 - Tebe
@AlexShulzhenko:关于可重入性和线程安全,我完全同意。在这里,“可重入”只是指内部数据存储(数组)是私有的,并且只能通过类方法访问和操作。参考: http://doc.qt.io/qt-5/threads-reentrancy.html#reentrant - kevinarpe
通常情况下这个规则是正确的,但Qt不仅仅是一个库,它是一个框架。如果你首先使用的是一个框架,那么全力以赴是有意义的。 - Mr. Developerdude

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接