i have main
QStack<TypeFoo*> MainStack
now i have from different objects methods output
QVector<TypeFoo*> OutPutVec
i like to add the elements of OutPutVec to MainStack without looping , just add them to the bottom if the stack , what is the best way to do this ? do i need to convert my OutPutVec
to QStack?
is this good and fast more then loop ?
QVector<T> & QVector::operator+= ( const QVector<T> & other )
QStack inherits QVector and QVector has the following definition:
QVector & operator<< ( const QVector & other )
Therefore you should be able to simply do
MainStack << OutPutVec;
Usually, I use operator << for append containers.
You can choose one of the variant.
This is realisation of operator +=
template <typename T>
QVector<T> &QVector<T>::operator+=(const QVector &l)
{
int newSize = d->size + l.d->size;
realloc(d->size, newSize);
T *w = p->array + newSize;
T *i = l.p->array + l.d->size;
T *b = l.p->array;
while (i != b) {
if (QTypeInfo<T>::isComplex)
new (--w) T(*--i);
else
*--w = *--i;
}
d->size = newSize;
return *this;
}
And realisation of operator <<
inline QVector<T> &operator<<(const QVector<T> &l)
{ *this += l; return *this; }
PS. Creating a loop to copy the data does not make sense, if you can use Qt "buns". Qt appends data faster, then your loop
PSS. If you read the assistant, you might find that the QStack is inherited from the QVector.
Related
After reading a number of questions on here such as Why doesn't QList have a resize() method?, I am wondering about the following.
Normally, in STL code I could have something like this to limit the size of results processed:
std::list<int> results = something()
results.resize(std::min(result.size(), 5000));
Now I have a Qt project with a QList:
QList<int> results = something()
while(results.size() > 5000) {
results.removeLast();
}
expensiveOperation(results);
Is this really the best way to to this with Qt containers a QList?
The reason is that I need to pass this eventually to a framework function expecting a QList.
QList != std::list. There's QLinkedList which is more like the std. version. For most operations QVector is preferred over QList as the container type to use in Qt. Read https://marcmutz.wordpress.com/effective-qt/containers/ for a full explanation.
If you're stuck with QList for some reason... then yeah... :( It may be quicker to get a new list with QList::mid(). And there's always QList::toVector() or toStdList(). :)
How about:
template<typename T>
static void truncate(QList<T> &list, int length) {
if (0 <= length && length < list.length()) {
list.erase(list.begin() + length, list.end());
}
}
I wrote a function to convert a hexa string representation (like x00) of some binary data to the data itself.
How to improve this code?
QByteArray restoreData(const QByteArray &data, const QString prepender = "x")
{
QByteArray restoredData = data;
return QByteArray::fromHex(restoredData.replace(prepender, ""));
}
How to improve this code?
Benchmark before optimizing this. Do not do premature optimization.
Beyond the main point: Why would you like to optimize it?
1) If you are really that concerned about performance where this negligible code from performance point of view matters, you would not use Qt in the first place because Qt is inherently slow compared to a well-optimized framework.
2) If you are not that concerned about performance, then you should keep the readability and maintenance in mind as leading principle, in which case your code is fine.
You have not shown any real world example either why exactly you want to optimize. This feels like an academic question without much pratical use to me. It would be interesting to know more about the motivation.
That being said, several improvement items, which are also optimization, could be done in your code, but then again: it is not done for optimization, but more like logical reasons.
1) Prepender is bad name; it is usually called "prefix" in the English language.
2) You wish to use QChar as opposed to QString for a character.
3) Similarly, for the replacement, you wish to use '' rather than the string'ish "" formula.
4) I would pass classes like that with reference as opposed to value semantics even if it is CoW (implicitly shared).
5) I would not even use an argument here for the prefix since it is always the same, so it does not really fit the definition of variable.
6) It is needless to create an interim variable explicitly.
7) Make the function inline.
Therefore, you would be writing something like this:
QByteArray restoreData(QByteArray data)
{
return QByteArray::fromHex(data.replace('x', ''));
}
Your code has a performance problem because of replace(). Replace itself is not very fast, and creating intermediate QByteArray object slows the code down even more. If you are really concerned about performance, you can copy QByteArray::fromHex implementation from Qt sources and modify it for your needs. Luckily, its implementation is quite self-contained. I only changed / 2 to / 3 and added --i line to skip "x" characters.
QByteArray myFromHex(const QByteArray &hexEncoded)
{
QByteArray res((hexEncoded.size() + 1)/ 3, Qt::Uninitialized);
uchar *result = (uchar *)res.data() + res.size();
bool odd_digit = true;
for (int i = hexEncoded.size() - 1; i >= 0; --i) {
int ch = hexEncoded.at(i);
int tmp;
if (ch >= '0' && ch <= '9')
tmp = ch - '0';
else if (ch >= 'a' && ch <= 'f')
tmp = ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
tmp = ch - 'A' + 10;
else
continue;
if (odd_digit) {
--result;
*result = tmp;
odd_digit = false;
} else {
*result |= tmp << 4;
odd_digit = true;
--i;
}
}
res.remove(0, result - (const uchar *)res.constData());
return res;
}
Test:
qDebug() << QByteArray::fromHex("54455354"); // => "TEST"
qDebug() << myFromHex("x54x45x53x54"); // => "TEST"
This code can behave unexpectedly when hexEncoded is malformed (.e.g. "x54x45x5" will be converted to "TU"). You can fix this somehow if it's a problem.
I was taught always to use a pointer list when storing objects, but I started using lists with objects in them instead. So I'm wondering how do I properly remove an object from a list?
The first code example removes from a pointer list and works all right, but the second one gives an error when running. Do I need to use delete when working with list with objects?
using namespace std;
struct SomeObject{
SomeObject(int i){
something=i;
}
int something;
};
void main(){
list<SomeObject*> pointerList;
SomeObject * op = new SomeObject(2);
pointerList.push_back(op);
auto pit = pointerList.begin();
pointerList.erase(pit);
delete *pit;
cout<<(**pit).something<<endl;
list<SomeObject> objectList;
SomeObject o(1);
objectList.push_back(o);
auto oit = objectList.begin();
objectList.erase(oit);
delete &oit;//this one
cout<<oit->something<<endl;
int i;
cin >> i;
}
Also what are down and upsides with doing it this way?
You get the error because oit is an iterator, not a pointer. You use delete on pointers acquired with new. Iterators look like pointers, but they are not pointers. In the example you gave it's just wrong to use delete.
I think it would be more idiomatic (and correct!) this way:
list<SomeObject*> pointerList;
SomeObject * op = new SomeObject(2);
pointerList.push_back(op);
auto pit = pointerList.front();
pointerList.pop_front();
// delete *pit; // wrong
cout << (**pit).something << endl;
list<SomeObject> objectList;
SomeObject o(1);
objectList.push_back(o);
auto oit = objectList.front();
objectList.pop_front();
// delete &oit; // wrong
cout << oit->something << endl;
Using Qt, I want this code to work:
QList<QPair<QString, QString>> list;
foreach (QPair<QString, QString> pair, list)
{
}
instead, I get the error:
'pair' : undeclared identifier
Using a typedef I can make it work, but this is not what I want (unless this is the only thing that works):
typedef QPair<QString, QString> MyPair;
QList<MyPair> list;
foreach (MyPair pair, list)
{
}
Can anyone explain why the first foreach doesn't compile?
it's not the foreach error. It's declaration error. You declared list like this:
QList<QPair<QString, QString>> list;
while it should this way:
QList<QPair<QString, QString> > list;
Just declare QPair outside of loop:
QPair<QString,QString> pair;
foreach(pair,list){
}
It is not possible to use template classes inside qt foreach statement which contains more than one template parameter, because comma separator conflicts with comma separator inside macros.
#define add( a, b ) (a + b)
template < typename T1, typename T2 >
struct DATA
{
static const T1 val1 = 1;
static const T2 val2 = 2;
};
// Usage
const int c = add( 1, 2 ); // OK
const int d = add( DATA< int, int >::val1 , DATA< int, int >::val2 ); // FAIL
because macros add will interpret "DATA< int" as first argument, and " int >::val1" as second, and so on.
Some explanation with above answer... if your compiler accept
QList<QPair<QString, QString>> list;
giving no error on such declaration, reasons for topic caster error is different and indeed has to do with a fact that declaration must be done outside of foreach() loop. That's explained in QT documentation.
regarding >> and > >... that's old story and latest GCC (so linux/mac) consider it to be a syntax mistake, because it's not conforming standard. >> in GCC manner is treated as operator with all follow-up errors..
This is a pretty simple and probably dumb question, but I have forgotten how to use QList QVariant::toList () const
QVariant s = this->page()->mainFrame()->evaluateJavaScript (QString ("Open(%1,%2)").arg (point.x()).arg (point.y()));
List<QVariant> x;
x = s.toList ();
Of course this is wrong, what is the correct way out? :redface:
What you do is almost correct:
QList<QVariant> x = s.toList();
(Note the use of QList instead of List.)
What you're doing is right. May be you can check if the variant contains a list before converting it. E.g:
QVariant variant = list;
if(variant.canConvert(QVariant::List))
{
QList<QVariant> list_1 = variant.toList();
}