using namespace std;
Olivier Goffart
http://woboq.com
QLineEdit::setText(const QString &)
_ZN9QLineEdit7setTextERK7QString
QLineEdit::setText(const std::string &)
_ZN9QLineEdit7setTextERKSs
_ZN9QLineEdit7setTextERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
☺ Qt compiled against one implementation is binary compatible with applications compiled against another implementation.
☹ Qt has to re-invent the wheel.
General purpose. Designed for everything.
Focus on making C++ easy to use for a GUI application.
QMap<Key, T>
std::map<Key, T, Compare, Allocator>
QHash<Key, T >
std::unordered_map<Key, T, Hash, KeyEqual, Allocator>
std::basic_string<CharT, Trait, Alloc>
Qt | STL |
---|---|
count, size, length
| size |
append, push_back |
push_back |
constBegin, cbegin |
cbegin |
operator[] |
operator[] |
value |
— |
Qt | STL |
---|---|
last, back
| back |
first, front
| front |
prepend, push_front
| push_front |
removeFirst, pop_front |
pop_front |
takeFirst |
— |
isEmpty, empty |
empty |
indexOf |
— (std::find) |
... |
Hint: When mixing Qt code and the standard library,
prefer the STL style
Attention: beware of the differences in at
and []
operator[]
might copy ⇒ prefer at()
at()
does runtime bound check ⇒ prefer []
QString str = "Hello World"; //1
QString str2 = str; //2
str.append("!"); //3
1
2
3
qSort(myVect);
std::sort(myVect.begin(), myVect.end());
All standard algorithms work with Qt containers.
QVector<Item> items = getMyList();
auto it = items.begin();
while(it != it.end()) {
if (it->priority() <= threshold)
it = items.erase(it);
else
++it;
}
QVector<Item> items = getAllItems();
auto it = std::remove_if(items.begin(), items.end(),
[&](const Item &it) {
return it.priority() <= threshold;
}));
items.erase(it, items.end());
const QVector<Item> items = getAllItems();
const QVector<Item> result;
foreach (const Item &it, items) {
if (it.priority() > threshold)
result.append(it);
}
const QVector<Item> items = getAllItems();
const QVector<Item> result;
std::copy_if(items.begin(), items.end(),
std::back_inserter(result),
[&](const Item &it) {
return it.priority() > threshold;
});
http://en.cppreference.com/w/cpp/algorithm
Use standard algorithms instead of rolling your own loop.
std::sort(myVect);
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0021r0.pdf
http://ericniebler.github.io/range-v3
Qt | STL |
---|---|
QVector | std::vector |
— | std::deque |
QList | — |
QLinkedList | std::list |
— | std::forward_list |
QVarLengthArray | — |
— | experimental::dynarray |
— | std::array |
QVector
vs. std::vector
Q_DECLARE_TYPEINFO
Q_DECLARE_TYPEINFO(MyType, Q_MOVABLE_TYPE);
Q_PRIMITIVE_TYPE
specifies that Type is a type with no constructor or destructorQ_MOVABLE_TYPE
specifies that Type can be moved in memory using memcpy().Q_COMPLEX_TYPE
(the default) specifies that Type may not be moved in memory.QList
No indirections if:
sizeof(T) <= sizeof(void*)
Q_DECLARE_TYPEINFO(T, Q_MOVABLE_TYPE)
std::deque
QVarLengthArray<T,Prealloc>
Warning: Default Prealloc = 256
QVarLengthArray
on the stack for usually small listsQVector
or std::vector
if you can use reserve()
, or need the elements contiguous.std::deque
if you need to insert elements at the begining.Avoid QList
unless you pass it to Qt API.
Qt | STL |
---|---|
QMap | std::map |
QMultiMap | std::multimap |
— | std::set, std::multiset |
QHash | std::unordered_map |
QMultiHash | std::unordered_multimap |
QSet | std::unordered_set |
— | std::unordered_multiset |
foreach
for(:)
begin()
and end()
const
)foreach | for(:) | |
---|---|---|
std::vector | Slow¹ | OK |
QVector | OK | Attention² |
QVarLengthArray | Slow¹ | OK |
foreach
makes a copy.Attention: Don't use the standard container in
Qt's foreach
.
Hint: Use Qt containers in for(:)
only if const
or not shared.
#define AS_CONST(OBJ) const_cast<const decltype(OBJ)&>(OBJ)
for(const auto &val : AS_CONST(getQVector())) /* ... */
Qt | STL |
---|---|
QByteArray | std::string |
QString | std::wstring, std::u16string |
QStringRef | — |
— | experimental::string_view |
QString(u"größte").toUpper(); // "GRÖSSTE"
std::u16string str = u"größte";
std::transform(str.begin(), str.end(),str.begin(),
towupper);
// "GRÖßTE"
bool isValidIdentifier(const QByteArray &id)
{
return d.size() > 3 && !id.endsWith("_w");
}
QByteArray myQBA = qmlView->getToken();
if (isValidIdentifier(myQBA)) {/* ... */}
std::string myStdStr = answomeLib->getId();
// Allocates!
if (isValidIdentifier(QByteArray::fromStdString(myStdStr))
{ /* ... */ }
template<typename T>
bool isValidIdentifier(const T &id);
bool isValidIdentifier(const char*);
string_view
bool isValidIdentifier(const string_view &id);
std::experimental::string_view
experimental
namespaceQt | STL |
---|---|
QScopedPointer | — |
— | std::unique_ptr |
QSharedPointer | std::shared_ptr |
QWeakPointer | std::weak_ptr |
QSharedDataPointer | — |
QExplicitlySharedDataPointer | — |
// Does this function take ownership of the pointer?
QAction *QMenu::addMenu(QMenu *);
void QGraphicsScene::addItem(QGraphicsItem *item);
// Do I have to delete the returned pointer ?
QLayoutItem * QLayout::takeAt(int index)
// Yes, takes ownership
void QGraphicsScene::addItem(std::unique_ptr<QGraphicsItem> item);
// Gives ownership
std::unique_ptr<QLayoutItem> QLayout::takeAt(int index);
QScopedPointer
is not movable (by design)std::vector<std::unique_ptr<FooBar>>
impossible with QVector or QScopedPointerShould you subclass QThread
?
You can also use std::thread
!
std::thread
(Signals-slots, QMutex, QThreadStorage, ...)std::mutex
, . also work in QThread
class MyObject : public QObject { /*...*/ std::thread worker; signals: void resultReady(quint64); };
void MyObject::startWorkInAThread() { Q_ASSERT(!m_worker.joinable()); // Already running? m_worker = std::thread( [=] { auto res = fib(n); /* expensive or blocking */ emit this->resultReady(res); } ); QObject::connect(this, &MyObject::resultReady, this, [=](quint64 val) { qDebug() << "Result:" << val; this->m_worker.join(); }); }
m_thread = std::thread( [=] {
QEventLoop loop;
WorkerObj worker;
QObject::connect(&worker, &WorkerObj::resultReady,
this, &MyObject::resultReady);
QObject::connect(&worker, &WorkerObj::resultReady,
QThread::currentThread(), &QThread::quit);
worker.start();
loop.exec();
});
Olivier Goffart
olivier@woboq.com
Twitter:
@woboq
std::string s1 = "Lorem ipsum dolor sit"; // allocates std::u16string s2 = "Lorem ipsum dolor sit"; // allocates QString s3 = "Lorem ipsum dolor sit"; // allocates QByteArray s4 = "Lorem ipsum dolor sit"; // allocates
// no allocations: QString s5 = QStringLiteral("Lorem ipsum dolor sit"); QByteArray s6= QByteArrayLiteral("Lorem ipsum dolor sit");
QString myString = "Head: " + head
+ "\nBody: " + body + '\n';
-D QT_USE_QSTRINGBUILDER
or
QString myString = "Head: " % head
% "\nBody: " % body % '\n';