我的问题基本上是何时选择QVector和何时选择QList作为您的Qt容器。我已经知道的:
For most purposes, QList is the right class to use. Its index-based API is more convenient than QLinkedList's iterator-based API, and it is usually faster than QVector because of the way it stores its items in memory. It also expands to less code in your executable.
QList效率都不高。每次添加新元素时,它都会调用new(每个元素一次),这与QVector相比效率低下。QVector作为默认容器吗?
最佳答案
Qt宣传 For most purposes, QList is the right class to use. For most purposes, QList will do.
QList为“万事通”,但那句话的另一半是“无主”。我想说QList是一个不错的选择,如果您打算追加到列表的两端,并且它们不大于指针,因为QList前后都保留了空间。就是这样,我的意思是就使用QList而言,有充分的理由。QList会自动将“大”对象存储为指针并在堆上分配对象,如果您是婴儿,这不知道如何声明QVector<T*>并使用动态分配,这可能是一件好事。这不一定是一件好事,在某些情况下,它只会使内存使用量过大,并增加额外的间接访问。 IMO总是明确指出所需的内容(无论是指针还是实例)都是一个好主意。即使您确实希望进行堆分配,也总是最好自己分配它,并简单地将指针添加到列表中,而不是一次构造该对象,然后在堆上进行复制构造。
Qt会在很多地方为您返回QList,例如在获得QObject的 child 或您搜索 child 时。在这种情况下,使用在第一个元素之前分配空间的容器是没有意义的,因为它是已经存在的对象的列表,而不是您可能会喜欢的对象。我也不太喜欢缺少resize()方法。
想象一下这样的情况:在64位系统上,您有一个9字节长且字节对齐的对象。对于QList来说“太多了”,因此它将使用8字节指针+ CPU开销进行缓慢的堆分配+内存开销进行堆分配。它将使用两倍的内存,并且具有额外的间接访问权限,因此几乎不会像所宣传的那样提供性能优势。
关于QVector为什么不能突然成为“默认”容器的原因-您不要在赛程中改变马匹-这是一件很古老的事情,Qt是如此旧的框架,即使很多东西已被弃用,也要进行更改并非总是可能使用广泛使用的默认值,并非不破坏大量代码或产生不良行为。无论好坏,QList在整个Qt 5中都可能一直是默认设置,并且在下一个主要发行版中也可能如此。在智能指针已成为必需品多年之后,并且所有人都在提示普通指针有多糟糕以及如何永远不使用它们之后,Qt将继续使用“哑”指针的原因相同。
话虽这么说,没有人强制您在设计中使用QList。没有理由不将QVector设为默认容器。我本人在任何地方都不使用QList,在返回QList的Qt函数中,我只是用作将内容移动到QVector的临时方法。
此外,这只是我个人的观点,但是我确实在Qt中发现了许多不必要的设计决策,例如性能或内存使用效率或明智的易用性,并且总体上有很多框架和喜欢推广自己的做事方式的语言,不是因为这是最好的做事方式,而是因为这是他们做事的方式。
最后但并非最不重要的:
真正归结为您如何理解这一点。国际海事组织在这种情况下,“正确”并不代表“最佳”或“最佳”,而是代表“足够好”,就像“即使不是最佳也可以做到”。特别是如果您对不同的容器类及其工作方式一无所知。
总结一下:QList专业人士
您打算在
您打算将QVector与显式指针一起使用,以实现相同且更便宜的方式-无需额外的复制),因为调整列表大小,将不移动任何对象,仅移动指针QList缺点resize()方法,reserve()是一个细微的陷阱,因为它不会增加有效列表的大小,即使索引访问有效,它也属于UB类别,您也将无法迭代该列表
由于最后两个,
CON的优势略大于PRO,这意味着虽然可以“随意”使用QList,但您绝对不希望在CPU时间和/或内存使用成为关键因素的情况下使用它。总而言之,当您不想为用例考虑最佳存储容器时,QList最适合懒惰和粗心的使用,通常是QVector<T>,QVector<T*>或QLinkedList(但我排除了“STL“容器,因为我们在这里谈论Qt,所以Qt容器具有可移植性,有时更快,并且最肯定更易于使用和清洁,而std容器则是不必要的冗长。
关于c++ - 重新访问QList与QVector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33609406/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案