Container STL hay Qt?


185

Ưu và nhược điểm của việc sử dụng container Qt (là gì QMap, QVectorvv) trên STL tương đương của họ?

Tôi có thể thấy một lý do để thích Qt:

  • Container Qt có thể được chuyển qua các phần khác của Qt. Ví dụ, chúng có thể được sử dụng để cư trúQVariant và sau đó một QSettings(với một số giới hạn, chỉ QListQMap/ QHashcó khóa là chuỗi được chấp nhận).

Có cái nào khác không?

Biên tập : Giả sử ứng dụng đã dựa vào Qt.

Câu trả lời:


135

Tôi đã bắt đầu bằng cách sử dụng std::(w)stringvà các bộ chứa STL độc quyền và chuyển đổi sang / từ các tương đương Qt, nhưng tôi đã chuyển sang QStringvà tôi thấy rằng tôi đang sử dụng các bộ chứa của Qt ngày càng nhiều.

Khi nói đến chuỗi, QStringcung cấp chức năng đầy đủ hơn nhiều so với std::basic_stringvà nó hoàn toàn nhận biết Unicode. Nó cũng cung cấp một triển khai COW hiệu quả , mà tôi đã dựa vào rất nhiều.

Container của Qt:

  • cung cấp triển khai COW tương tự như trong QString, cực kỳ hữu ích khi sử dụng foreachmacro của Qt (bản sao) và khi sử dụng loại meta hoặc tín hiệu và vị trí.
  • có thể sử dụng các trình vòng lặp kiểu STL hoặc các trình vòng lặp kiểu Java
  • có thể truyền phát với QDataStream
  • được sử dụng rộng rãi trong API của Qt
  • có một triển khai ổn định trên các hệ điều hành. Việc triển khai STL phải tuân theo tiêu chuẩn C ++, nhưng về mặt khác thì được tự do thực hiện (xem phầnstd::string tranh cãi COW). Một số triển khai STL đặc biệt xấu.
  • cung cấp băm, không có sẵn trừ khi bạn sử dụng TR1

QTL có một triết lý khác với STL, được J. Blanchette tóm tắt : "Trong khi các container của STL được tối ưu hóa cho tốc độ thô, các lớp container của Qt đã được thiết kế cẩn thận để cung cấp sự tiện lợi, sử dụng bộ nhớ tối thiểu và mở rộng mã tối thiểu."
Liên kết trên cung cấp thêm chi tiết về việc triển khai QTL và những gì tối ưu hóa được sử dụng.


12
Trong tiêu chuẩn mới c ++ 0x COW thì khá nhiều.

16
re: "được thiết kế cẩn thận để cung cấp [...] mức sử dụng bộ nhớ tối thiểu". Bạn không nên tin vào marketing. Hồ sơ QList<double>trên kiến ​​trúc 32 bit để sử dụng bộ nhớ để tự mình xem.
Marc Mutz - mmutz

11
"Nó cũng cung cấp một triển khai COW hiệu quả": COW không hiệu quả lắm khi nói đến các ứng dụng đa luồng ...
Grizzly

5
@ MarcMutz-mmutz cố gắng hồ sơ QVectorthay vì QList. Có nhiều lời giải thích về Qt, rằng QList được thiết kế để lưu trữ các con trỏ trên các đối tượng. Vì vậy, mỗi mục kép được tạo động và con trỏ tới mục này được lưu trữ QList. QList được thiết kế là vùng chứa "giữa" giữa vector và danh sách được liên kết. Nó không được thiết kế cho các trường hợp quan trọng về bộ nhớ / hiệu năng.
Dmitry Sazonov

2
@ user1095108 Không có gì sai với điều đó. Đi sử dụng stl. Một số người trong chúng ta thích viết mã chính xác một cách nhanh chóng. Không có gì sai với điều đó cả.
weberc2

178

Đây là một câu hỏi khó trả lời. Nó thực sự có thể sôi sục với một lập luận triết học / chủ quan.

Điều đó đang được nói ...

Tôi đề nghị quy tắc "Khi ở Rome ... Làm như người La Mã làm"

Điều đó có nghĩa là nếu bạn ở vùng đất Qt, hãy viết mã như người Qt làm. Điều này không chỉ dành cho mối quan tâm dễ đọc / nhất quán. Hãy xem xét những gì xảy ra nếu bạn lưu trữ mọi thứ trong một thùng chứa stl thì bạn phải chuyển tất cả dữ liệu đó sang một hàm Qt. Bạn có thực sự muốn quản lý một loạt các mã sao chép mọi thứ vào / ra khỏi các thùng chứa Qt. Mã của bạn đã phụ thuộc rất nhiều vào Qt, do đó, không giống như bạn đang làm cho nó trở nên "chuẩn" hơn bằng cách sử dụng các thùng chứa stl. Và điểm của một container là gì nếu mỗi khi bạn muốn sử dụng nó cho bất cứ điều gì hữu ích, bạn phải sao chép nó vào container Qt tương ứng?


1
+1 bạn hoàn toàn đúng, đó là những gì tôi đã cố gắng giải thích trong câu hỏi của mình ("Tôi có thể thấy một lý do để thích Qt") vì vậy tôi đã chỉnh sửa nó một chút. Cảm ơn
Julien-L

Hoàn toàn nói tốt. Nếu bạn đang làm QT, hãy sử dụng công cụ QT! Hãy tưởng tượng khoảnh khắc "WTF" cho người bảo trì khi anh ta mở một ứng dụng QT và thấy QT và STL được sử dụng thay thế cho nhau. Điều đó có thể trở thành một cơn ác mộng (không cần thiết).
Đó là

5
@ ItsPete STL là một phần của tiêu chuẩn; QT thì không. Bất kỳ mã nào sử dụng tiêu chuẩn sẽ không bao giờ kích hoạt khoảnh khắc "WTF".
Alice

5
Người La Mã đưa tù nhân của họ vào Đấu trường La Mã và sau đó săn lùng chúng cùng với sư tử. Nếu bạn biết rõ hơn, đừng làm theo thói quen địa phương. Điều đó đúng với Qt như lẽ ra đối với Người hiện đại trong Đế chế La Mã ...
Marc Mutz - mmutz

1
@mmutz bạn nói rằng đó là một điều tồi tệ, tôi muốn đặt một số mã tôi đã tìm thấy trong Colosseum đó và xem chương trình
slf

64

Các thùng chứa Qt bị hạn chế hơn so với STL. Một vài ví dụ về nơi STL vượt trội (tất cả những thứ tôi đã đánh trong quá khứ):

  • STL được chuẩn hóa, không thay đổi với mọi phiên bản Qt (Qt 2 có QList(dựa trên con trỏ) và QValueList(dựa trên giá trị); Qt 3 đã có QPtrListQValueList; Qt 4 hiện có QList, và không có gì giống như QPtrList hoặc QValueList ).
    Ngay cả khi bạn kết thúc bằng cách sử dụng các bộ chứa Qt, hãy sử dụng tập hợp con API tương thích STL (nghĩa là push_back(), không append(); front(), khôngfirst() , ...) để tránh chuyển tiếp một lần nữa đến Qt 5. Trong cả Qt2-> 3 và Qt3-> 4 chuyển đổi, những thay đổi trong các thùng chứa Qt nằm trong số những chuyển đổi đòi hỏi nhiều mã nhất.
  • Tất cả các container hai chiều STL đều có rbegin()/ rend(), làm cho phép lặp ngược đối xứng để lặp lại. Không phải tất cả các thùng chứa Qt đều có chúng (những cái kết hợp không có), vì vậy việc lặp lại rất phức tạp.
  • Các thùng chứa STL có phạm vi - insert()từ các loại trình lặp khác nhau, nhưng tương thích, khiến cho việc sử std::copy()dụng ít thường xuyên hơn.
  • Các bộ chứa STL có một Allocatorđối số mẫu, làm cho việc quản lý bộ nhớ tùy chỉnh trở nên tầm thường (yêu cầu typedef), so với Qt (fork của QLineEdityêu cầu cho s/QString/secqstring/). EDIT 20171220 : Điều này cắt giảm Qt những tiến bộ trong thiết kế phân bổ theo C ++ 11 và C ++ 17, x. ví dụ như bài nói chuyện của John Lakos ( phần 2 ).
  • Không có Qt tương đương với std::deque .
  • std::listsplice(). Bất cứ khi nào tôi thấy mình sử dụng std::list, đó là vì tôi cần splice().
  • std::stack, std::queuetổng hợp chính xác thùng chứa bên dưới của chúng và không kế thừa nó, như QStack, QQueuelàm.
  • QSetlà thích std::unordered_set, không thích std::set.
  • QListlà một chỉ lạ .

Nhiều điều ở trên có thể được giải quyết khá dễ dàng trong Qt , nhưng thư viện container trong Qt dường như gặp phải sự thiếu tập trung phát triển vào lúc này.

EDIT 20150106 : Sau khi dành một chút thời gian để cố gắng mang hỗ trợ C ++ 11 cho các lớp container Qt 5, tôi đã quyết định rằng nó không đáng để làm việc. Nếu bạn nhìn vào công việc đang được đưa vào triển khai thư viện chuẩn C ++, thì rõ ràng các lớp Qt sẽ không bao giờ theo kịp. Chúng tôi đã phát hành Qt 5.4 ngay bây giờ vàQVector vẫn không di chuyển các yếu tố trên các phân bổ lại, không cóemplace_back()hoặc xác định giá trị-push_back()... Gần đây chúng tôi cũng đã từ chối mộtQOptionalmẫu lớp, chờ đợistd::optionalthay thế. Tương tự như vậy chostd::unique_ptr. Tôi hy vọng xu hướng đó tiếp tục.


3
Huh. Tôi đã có ấn tượng QList tương đương với std::deque. Rõ ràng, tôi không nên đọc lướt tài liệu.
Dennis Zickefoose

QVectorđã có crbeginvà bạn bè kể từ Qt 5.6
Bart Louwers

@Alex: đúng, tôi đã thêm những cái dễ, nhưng không phải tất cả các thùng chứa Qt đều có chúng (vì bạn không sử dụng std::reverse_iteratorqua các bộ lặp QHash/ hỏng QMap, khi bị hủy đăng ký, hãy trả lại mapped_typethay vì value_type). Không có gì không thể sửa được, nhưng hãy xem EDIT của tôi từ năm 2015.
Marc Mutz - mmutz

@ MarcMutz-mmutz Cảm ơn bạn đã làm rõ.
Bart Louwers

Có thể đáng để thêm vào danh sách thực tế, ví dụ như QVectorsử dụng intlàm chỉ mục của nó, do đó hạn chế kích thước 31 bit (ngay cả trên các hệ thống 64 bit). Hơn nữa, nó thậm chí không thể lưu trữ INT_MAXcác phần tử có kích thước lớn hơn 1 byte. Ví dụ: phần lớn nhất .size()tôi có thể có QVector<float>trên x86_64 Linux gcc là 536870907 phần tử (2²⁹-5), trong khi std::vector<float>đã phân bổ thành công 4294967295 phần tử (2³²-1; ).
Ruslan

31

Hãy chia nhỏ những tuyên bố này thành những hiện tượng có thể đo lường được:

  • Nhẹ hơn: Container Qt sử dụng ít bộ nhớ hơn container STL
  • An toàn hơn: Container Qt có ít cơ hội được sử dụng không đúng cách
  • Dễ dàng hơn: Các thùng chứa Qt thể hiện ít gánh nặng trí tuệ hơn

Dễ dàng hơn

Khiếu nại được đưa ra trong ngữ cảnh này là việc lặp theo kiểu java bằng cách nào đó "dễ dàng" hơn kiểu STL, và do đó Qt dễ sử dụng hơn do giao diện bổ sung này.

Phong cách Java:

QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

Phong cách STL:

QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

Kiểu trình lặp Java có lợi ích là nhỏ hơn và sạch hơn một chút. Vấn đề là, đây không thực sự là phong cách STL nữa.

Phong cách C ++ 11 STL

for( auto i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

hoặc là

Phong cách foreach C ++ 11

for (QString i : list)
    qDebug << i;

Điều này đơn giản đến mức không có lý do gì để sử dụng bất cứ thứ gì khác (trừ khi bạn không hỗ trợ C ++ 11).

Tuy nhiên, yêu thích của tôi là:

BOOST_FOREACH(QString i, list)
{
    qDebug << i;
}

Vì vậy, như chúng ta có thể thấy, giao diện này không mang lại cho chúng ta điều gì ngoại trừ một giao diện bổ sung, bên trên một giao diện hiện đại, đẹp mắt và hợp lý. Thêm một mức độ trừu tượng không cần thiết trên giao diện đã ổn định và có thể sử dụng? Không phải ý tưởng của tôi về "dễ dàng hơn".

Ngoài ra, giao diện Qt foreach và java thêm chi phí; họ sao chép cấu trúc, và cung cấp một mức độ không cần thiết. Điều này có vẻ không nhiều, nhưng tại sao lại thêm một lớp chi phí để cung cấp giao diện không đơn giản hơn nhiều? Java có giao diện này vì java không có quá tải toán tử; C ++ nào.

An toàn hơn

Sự biện minh mà Qt đưa ra là vấn đề chia sẻ ngầm, không phải là vấn đề ngầm hay vấn đề. Nó không liên quan đến việc chia sẻ, tuy nhiên.

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/

Đầu tiên, đây không phải là ẩn ý; bạn rõ ràng đang gán một vectơ cho một vectơ khác. Đặc tả trình lặp STL chỉ rõ rằng các trình vòng lặp thuộc về vùng chứa, vì vậy chúng tôi đã giới thiệu rõ ràng một vùng chứa chung giữa b và a. Thứ hai, đây không phải là một vấn đề; miễn là tất cả các quy tắc của đặc tả iterator được tuân theo, hoàn toàn không có gì sai. Lần duy nhất có sự cố xảy ra là ở đây:

b.clear(); // Now the iterator i is completely invalid.

Qt chỉ định điều này như thể nó có ý nghĩa gì đó, giống như một vấn đề phát sinh từ kịch bản này. Nó không. Trình lặp không hợp lệ và giống như bất kỳ thứ gì có thể được truy cập từ nhiều vùng khác nhau, đây chỉ là cách nó hoạt động. Trên thực tế, điều này sẽ xảy ra dễ dàng với các trình vòng lặp kiểu Java trong Qt, nhờ nó phụ thuộc rất nhiều vào việc chia sẻ ngầm, đó là một phản đề như được ghi lại ở đây và tại nhiều khu vực khác . Điều này có vẻ đặc biệt kỳ lạ đối với việc "tối ưu hóa" này được đưa vào sử dụng trong một khuôn khổ ngày càng hướng tới đa luồng, nhưng đó là tiếp thị cho bạn.

Bật lửa

Đây là một chút phức tạp hơn. Việc sử dụng các chiến lược tăng trưởng và chia sẻ sao chép và ghi lại tiềm ẩn khiến cho việc thực sự đảm bảo về việc bộ nhớ của bạn sẽ sử dụng bao nhiêu bộ nhớ tại bất kỳ thời điểm nào. Điều này không giống như STL, mang đến cho bạn sự đảm bảo về thuật toán mạnh mẽ.

Chúng ta biết giới hạn tối thiểu của không gian bị lãng phí cho một vectơ là căn bậc hai của chiều dài của vectơ , nhưng dường như không có cách nào để thực hiện điều này trong Qt; các "tối ưu hóa" khác nhau mà họ hỗ trợ sẽ loại trừ tính năng tiết kiệm không gian rất quan trọng này. STL không yêu cầu tính năng này (và hầu hết sử dụng tăng trưởng gấp đôi, sẽ lãng phí hơn), nhưng điều quan trọng cần lưu ý là ít nhất bạn có thể thực hiện tính năng này, nếu cần.

Điều tương tự cũng đúng với các danh sách được liên kết đôi, có thể sử dụng liên kết XOr để giảm đáng kể dung lượng sử dụng. Một lần nữa, điều này là không thể với Qt, do yêu cầu của nó đối với tăng trưởng và COW.

COW thực sự có thể làm cho thứ gì đó nhẹ hơn, nhưng các Intrusive Container cũng có thể, như được hỗ trợ bởi boost và Qt đã sử dụng chúng thường xuyên trong các phiên bản trước, nhưng chúng không được sử dụng nhiều nữa vì chúng khó sử dụng, không an toàn và gây gánh nặng về lập trình viên. COW là một giải pháp ít xâm phạm hơn, nhưng không hấp dẫn vì những lý do nêu trên.

Không có lý do tại sao bạn không thể sử dụng các bộ chứa STL với cùng chi phí bộ nhớ hoặc ít hơn bộ chứa của Qt, với lợi ích bổ sung là thực sự biết bạn sẽ lãng phí bao nhiêu bộ nhớ tại bất kỳ thời điểm nào. Thật không may, không thể so sánh hai cách sử dụng bộ nhớ thô, bởi vì các điểm chuẩn như vậy sẽ cho thấy kết quả rất khác nhau trong các trường hợp sử dụng khác nhau, đây là loại vấn đề chính xác mà STL được thiết kế để khắc phục.

Tóm lại là

Tránh sử dụng Bộ chứa Qt khi có thể làm như vậy mà không áp dụng chi phí sao chép và sử dụng phép lặp loại STL (có thể thông qua trình bao bọc hoặc cú pháp mới), bất cứ khi nào có thể.


4
Điểm của bạn phần lớn là hợp lệ, nhưng có một số thông tin sai lệch trong đó: Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".Các trình lặp kiểu Java của Qt không được thêm vào C ++ 11; họ có trước nó Dù sao Qt's foreach(QString elem, list)cũng dễ như foreach của C ++ 11 hoặc BOOST_FOREACH và nó hoạt động với các trình biên dịch tuân thủ trước C ++ 11.
weberc2

@ weberc2 Bạn bối rối; Các trình vòng lặp kiểu Java của Qt được thêm vào trên các trình vòng lặp C ++ (không phải C ++ 11). Đó là một lớp trừu tượng bổ sung (và một lớp không cần thiết) làm mờ giao diện, điều này không dễ dàng hơn. Và foreach cho Qt không dễ như BOOST_FOREACH, vì nó đáng chú ý là không an toàn và không có cùng độ rộng hỗ trợ (BOOST_FOREACH có thể áp dụng cho bất kỳ phạm vi nào, cho bất kỳ phiên bản nào của C ++, trong đó như foreach trong QT yêu cầu C + +03 tuân thủ). Cần tránh các nghiên cứu của QT bằng mọi giá.
Alice

So, as we can see, this interface gains us nothing except an additional interface, *on top of* an already sleek, streamlined, and modern interface. Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".(nhấn mạnh của tôi) Bạn đã nói điều này ngay sau khi bạn cho chúng tôi xem phiên bản foreach C ++ 11 và BOOST, làm cho nó có vẻ như phiên bản Qt được tạo ra từ một trong hai phiên bản đó, không phải là trường hợp AFAICT. Tôi chắc chắn đó không phải là ý bạn, nhưng đó là cách nó diễn ra. Do đó "thông tin sai lệch".
weberc2

It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier.Vẫn chưa rõ những gì bạn đang so sánh với. C ++ 03 lặp? Lặp lại C ++ 11? BOOST_FOREACH? Tất cả những điều trên?
weberc2

1
Tôi chỉ nói rằng, bạn thường rất mơ hồ về phương pháp lặp mà bạn đang đề cập. Tôi tin rằng bạn nghĩ rằng bạn rõ ràng và ngôn ngữ của bạn là hợp lý, nhưng có vẻ lạ khi từ chối chỉ định. Đồng ý không đồng ý, tôi cho là vậy.
weberc2

22

Container STL:

  • Có đảm bảo hiệu suất
  • Có thể được sử dụng trong các thuật toán STL cũng có đảm bảo hiệu suất
  • Có thể được các thư viện C ++ của bên thứ ba tận dụng như Boost
  • Là tiêu chuẩn, và có khả năng tồn tại lâu hơn các giải pháp độc quyền
  • Khuyến khích lập trình chung các thuật toán và cấu trúc dữ liệu. Nếu bạn viết các thuật toán và cấu trúc dữ liệu mới phù hợp với STL, bạn có thể tận dụng những gì STL đã cung cấp miễn phí.

5
Tất cả những điều trên trừ việc trở thành một tiêu chuẩn cũng đúng với QTL, miễn là bạn biên dịch Qt với hỗ trợ STL (mặc định). Hỗ trợ STL bao gồm các hàm lặp, typedefs container (const_iterator, v.v.), các hàm chuyển đổi (đến / từ STL).
rpg

2
Qt không phải là độc quyền
txwikinger

2
@rpg Hầu như tất cả chúng đều không đúng với QTL; QTL không có đảm bảo hiệu suất mạnh (vì chúng đã dễ dàng phá vỡ chúng trong quá khứ), không tuân thủ STL (không đảo ngược và do đó không thể được sử dụng bởi nhiều tăng), không phải là tiêu chuẩn (chúng thay đổi liên tục giữa các phiên bản) và làm không khuyến khích lập trình chung (ví dụ, họ không có đối số mẫu cho các cấp phát).
Alice

15

Các thùng chứa Qt sử dụng thành ngữ copy-on-write.


2
+1, có thể là một lợi thế đáng kể về hiệu suất và tài nguyên
RedGlyph

31
Hoặc có thể là một bất lợi đáng kể. Xem gotw.ca/publications/optimizes.htmlm
Kaz Dragon

3
Số lượt truy cập nguyên tử dường như khá tốt: labs.trolltech.com/bloss/2006/10/16/iêu
rpg

Các thùng chứa STL có thể tự do sử dụng bất cứ thành ngữ nào tồn tại miễn là chúng đáp ứng các đảm bảo về hiệu suất và thông số kỹ thuật. COW là hợp lệ, ngay cả dưới C ++ 11 / C ++ 14 STL.
Alice

1
@Alice COW không phải là một triển khai hợp lệ hầu hết thời gian vì nó phá vỡ sự phức tạp của tiêu chuẩn và đảm bảo tính hợp lệ của trình lặp trong hầu hết mọi trường hợp. Một trong số ít các lớp có thể được thực hiện với COW là std::basic_stringvà tiêu chuẩn đã thực hiện các hành động với C ++ 11 để làm cho điều này không phù hợp.
Tiago Gomes

9

Một trong những vấn đề chính là API của Qt mong bạn cung cấp dữ liệu trong các thùng chứa của Qt, vì vậy bạn cũng có thể chỉ cần sử dụng các thùng chứa Qt thay vì chuyển đổi qua lại giữa hai.

Ngoài ra, nếu bạn đã sử dụng các bộ chứa Qt, có thể sử dụng chúng một cách tối ưu hơn một chút, vì bạn sẽ không phải bao gồm các tệp tiêu đề STL và có khả năng liên kết trong các thư viện STL. Tuy nhiên, tùy thuộc vào chuỗi công cụ của bạn, điều đó có thể xảy ra bằng mọi cách. Hoàn toàn từ quan điểm thiết kế, tính nhất quán nói chung là một điều tốt.


1
Tốc độ mà bạn phải "chuyển đổi qua lại" giữa các thùng chứa STL và Qt trong một ứng dụng thực sự sử dụng STL trừ khi giao tiếp với Qt thường được đánh giá quá cao. Hầu hết thời gian bạn thực hiện một số chuyển đổi std :: đến / từ lớp trình bày (sử dụng Qt) và bạn nhận được chuyển đổi container miễn phí. Các bên quan tâm có thể duyệt qua các dự án.kde.org / project / kde / kdepim / repposeective / revutions / giả để tự mình xem.
Marc Mutz - mmutz

8

Nếu dữ liệu bạn đang làm việc chủ yếu được sử dụng để điều khiển UI dựa trên Qt, thì chắc chắn sử dụng các thùng chứa Qt.

Nếu dữ liệu chủ yếu được sử dụng nội bộ trong ứng dụng và bạn sẽ không bao giờ chuyển khỏi Qt, sau đó chặn các vấn đề về hiệu suất, hãy sử dụng các thùng chứa Qt vì nó sẽ giúp xử lý các bit dữ liệu đến UI dễ dàng hơn.

Nếu dữ liệu chủ yếu được sử dụng cùng với các thư viện khác chỉ biết về các thùng chứa STL, thì hãy sử dụng các thùng chứa STL. Nếu bạn gặp phải tình huống này, bạn sẽ gặp rắc rối, không có vấn đề gì vì bạn sẽ thực hiện nhiều thao tác chuyển qua lại giữa các loại container cho dù bạn có làm gì đi nữa.


7

Bên cạnh sự khác biệt COW, các container STL được hỗ trợ rộng rãi hơn nhiều trên nhiều nền tảng khác nhau. Qt đủ khả năng di động nếu bạn giới hạn công việc của mình ở các nền tảng "chính thống", nhưng STL cũng có sẵn trên nhiều nền tảng khó hiểu khác (ví dụ, DSP của Texas Cụ).

Bởi vì STL là tiêu chuẩn chứ không phải do một công ty duy nhất kiểm soát, nói chung, có nhiều lập trình viên có thể dễ dàng đọc, hiểu và sửa đổi mã STL và nhiều tài nguyên hơn (sách, diễn đàn trực tuyến, hội nghị, v.v.) để hỗ trợ họ làm điều này hơn là cho Qt. Điều đó không có nghĩa là người ta nên tránh xa Qt chỉ vì lý do này; chỉ là, tất cả những thứ khác đều bằng nhau, bạn nên mặc định với STL, nhưng tất nhiên tất cả mọi thứ hiếm khi bằng nhau, vì vậy bạn sẽ phải quyết định trong bối cảnh của riêng bạn có ý nghĩa nhất.

Liên quan đến câu trả lời của AlexKR: hiệu suất STL được đảm bảo trong giới hạn, nhưng việc triển khai nhất định có thể sử dụng các chi tiết phụ thuộc vào nền tảng để tăng tốc STL của họ. Vì vậy, theo nghĩa đó, bạn có thể nhận được các kết quả khác nhau trên các nền tảng khác nhau, nhưng nó sẽ không bao giờ chậm hơn bảo đảm rõ ràng (lỗi modulo).


9
Liên quan đến điểm đầu tiên của bạn: Tôi cho rằng OP đang đề cập đến các dự án đã sử dụng Qt, và do đó đã bị giới hạn trong các nền tảng "chính thống". Dường như không ai có thể kéo vào một thư viện hạng nặng như Qt chỉ cho các lớp container của nó.
ThisSuitIsBlackNot

4

Năm xu của tôi: Các thùng chứa Qt được cho là hoạt động tương tự trên các nền tảng khác nhau. Trong khi các container STL phụ thuộc vào việc thực hiện STL. Bạn có thể nhận được kết quả hiệu suất khác nhau.

EDIT: Tôi không nói rằng STL là "chậm hơn" nhưng tôi chỉ ra tác động của các chi tiết thực hiện khác nhau.
Vui lòng kiểm tra cái này , và sau đó có thể cái này .
Và nó không phải là một vấn đề thực sự của STL. Rõ ràng, nếu bạn có sự khác biệt đáng kể về hiệu suất, thì có vấn đề trong mã sử dụng STL.


Các container STL đều tương tự nhau, không phân biệt việc thực hiện. Bạn không thể có một vectơ được triển khai như một danh sách đằng sau hậu trường vì nó phải nằm trong một khối bộ nhớ liền kề. STL cũng thường được tối ưu hóa ở mức độ lớn trên tất cả các nền tảng chính.
Yacoby

1
Nếu bạn tuân thủ những gì STL hứa hẹn (thay vì giả định cách thức triển khai), bạn sẽ không bao giờ gặp vấn đề khi di chuyển giữa các nền tảng với STL. Tương tự với Qt.
Michael Kohne

Điều này hoàn toàn ngược lại với sự thật. Các thùng chứa STL luôn hoạt động như nhau trên tất cả các nền tảng; nếu họ không, họ không STL. Tuy nhiên, QT thay đổi mạnh mẽ hiệu suất từ ​​phiên bản này sang phiên bản khác, vì vậy trên nền tảng với QT4.0 thay vì QT4.8, bạn có thể nhận được một số thay đổi nghiêm trọng.
Alice

Bạn đang nhầm lẫn hai loại hiệu suất rất khác nhau; hiệu suất thuật toán và hiệu suất tính toán thực tế. Tất cả các triển khai STL đảm bảo hiệu suất thuật toán giống nhau; nếu vectơ của bạn mất thời gian log (n) để lập chỉ mục cho một phần tử, thì đó không phải là vectơ STL. Liên kết của bạn chỉ ra hiệu suất tính toán thực tế, điều này là vô nghĩa trong cuộc thảo luận này; QT thay đổi thuật toán giữa các phiên bản và cùng C ++ trên các nền tảng khác nhau sẽ có hiệu suất khác nhau. Theo kinh nghiệm của tôi, chúng dễ uốn hơn nhiều so với sự khác biệt về hiệu suất STL.
Alice

3

Tôi đoán nó phụ thuộc vào cách bạn sử dụng Qt. Nếu bạn sử dụng nó trên tất cả các sản phẩm của bạn, thì có lẽ nên sử dụng các thùng chứa Qt. Nếu bạn chỉ chứa nó (ví dụ) phần UI, có thể tốt hơn là sử dụng các thùng chứa tiêu chuẩn C ++.


3

Tôi cho rằng STL là một phần mềm xuất sắc, tuy nhiên nếu tôi thực hiện một số chương trình liên quan đến KDE hoặc Qt thì Qt là con đường để đi. Ngoài ra, nó phụ thuộc vào trình biên dịch bạn đang sử dụng, với GCC STL hoạt động khá tốt tuy nhiên nếu bạn phải sử dụng SUN Studio CC thì STL rất có thể sẽ khiến bạn đau đầu vì trình biên dịch không phải STL mỗi lần. Trong trường hợp đó vì trình biên dịch sẽ làm cho đầu bạn bị tổn thương, chỉ cần sử dụng Qt để cứu bạn khỏi rắc rối. Chỉ 2 xu của tôi ...


3

Có một hạn chế (đôi khi) lớn trong QVector. Nó chỉ có thể phân bổ int byte bộ nhớ (lưu ý rằng giới hạn tính bằng byte không theo số lượng phần tử). Điều này ngụ ý rằng việc cố gắng phân bổ các khối bộ nhớ liền kề lớn hơn ~ 2GB với QVector sẽ dẫn đến sự cố. Điều này xảy ra với Qt 4 và 5. std :: vector không có giới hạn như vậy.


0

Lý do chính để đi với các container STL cho tôi là nếu bạn cần một bộ cấp phát tùy chỉnh để sử dụng lại bộ nhớ trong các thùng chứa rất lớn. Ví dụ, giả sử bạn có QMap lưu trữ 1000000 mục (cặp khóa / giá trị). Trong Qt ngụ ý chính xác 1000000 triệu phân bổ ( newcuộc gọi) không có vấn đề gì. Trong STL, bạn luôn có thể tạo một bộ cấp phát tùy chỉnh phân bổ nội bộ tất cả bộ nhớ đó cùng một lúc và gán nó cho từng mục khi bản đồ được điền.

Lời khuyên của tôi là sử dụng các thùng chứa STL khi viết các thuật toán quan trọng về hiệu suất trong logic nghiệp vụ và sau đó chuyển đổi chúng trở lại thành các thùng chứa Qt khi kết quả đã sẵn sàng bằng cách hiển thị bởi các điều khiển và biểu mẫu UI của bạn nếu cần.


Không cố gắng bảo vệ QTL ở đây, nhưng bạn có thể chuyên QMapNode<K,V>cho bạn K, Vđể cung cấp cho riêng bạn operator new.
Marc Mutz - mmutz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.