PDA

View Full Version : using QStringRef



mentalmushroom
1st March 2011, 14:30
Hello. I am trying to use QString objects effeciently, e.g. in my app I need to convert numbers that follow some text like 'code=124253'. It is convenient to use midRef to access the string containing only the digits, but it doesn't allow to call toInt() to translate them. QStringRef's string member simply returns the pointer to the initial string, so it is useless in this case also. So, although I can access the needed data I can't use it without creating a new QString object. QStringRef seems to be a bit useless being too restricted in its functionality. Is there any way to operate with QStringRef like with QString objects, at least how to convert QStringRef to integer without additional memory allocation?

high_flyer
2nd March 2011, 10:22
am trying to use QString objects effeciently
So does it mean that you have profiled your code and identified that a code using QStringRef is more efficient in your case that using QString?


We suggest that you only use this class in stable code where profiling has clearly identified that performance improvements can be made by replacing standard string operations with the optimized substring handling provided by this class.


It is convenient to use midRef to access the string containing only the digits, but it doesn't allow to call toInt() to translate them. QStringRef's string member simply returns the pointer to the initial string, so it is useless in this case also.
As it says in the docs:

QStringRef provides a read-only subset of the QString API.
Its not meant for string manipulation, but as more efficient access to substrings, which you can then evaluate (not same as manipulate).
But you will have to perform any non read only operations on a QString object.

Note that QString is a shared memory class, which is highly optimized.
I doubt that what you do is really effected by the reference counting overhead, such, that the benefit of the fact its shared is smaller. (unless, as I said at the start, you profiled to show otherwise).

mentalmushroom
2nd March 2011, 10:33
I don't know what is profiling, I just thought I don't need to modify any characters of the source string and using midRef instead of mid would be better in terms of performance. All I need is to convert some part of the string to a number. According to what is said in the doc (or how I understand that) mid function creates a new string consisting of the part of initial string, while midRef returns a part of the initial string without copying the characters. But if QString is really so highly optimized that it knows when mid should create a copy of the character set or just return the existing one, there is no problem, the only question why QStringRef was added at all if QString has the same performance?

high_flyer
2nd March 2011, 10:51
I don't know what is profiling,
Profiling (http://en.wikipedia.org/wiki/Profiling_%28computer_programming%29).
In short and very simplified, its measuring software performance.

But if QString is really so highly optimized that it knows when mid should create a copy of the character set or just return the existing one
Well, as all implicitly shared (http://doc.qt.nokia.com/4.7-snapshot/implicit-sharing.html) classes.


the only question why QStringRef was added at all if QString has the same performance?
Not same performance.
QStringRef is more efficient for referencing data.
But is not meant for manipulating it.
I didn't check, but I am very sure that QString is using QStringRef internally, and is there for you if you need to make your own QString similar classes.

But in usual cases, as the doc says, you should use QString.

mentalmushroom
2nd March 2011, 10:53
ok, thank you

wysota
2nd March 2011, 11:47
One thing though. mid() will always create a copy. Implicit sharing is only relevant for situations when entire object data is shared, not parts of it.

mentalmushroom
2nd March 2011, 11:55
hmm.. so that's bad. in old c code i could convert a part of a string doing something like this:


char * str = "code=123";
int value;
sscanf(str+5, "%d", &value);


so, there is no extra copy - i simply use the same data that i don't need to change. i'd like to do the same in qt with something like:


QString s("code=123");
int code = s.midRef(5).toInt();


but as far as i understood there is no way to do it. it would be great if a QStringRef had such functions or had a QString pointer to the part of data (not to the whole source string)

wysota
2nd March 2011, 12:20
With QString you can't use sscanf() because the data is unicode. But making a copy of three characters is not that painful :) QStringRef can't have too many methods because one of its purposes is to be lightweight. You can always use this stand-alone function:

quint32 toUInt(const QStringRef& ref, bool *ok = 0){
const int size = ref.size();
quint32 value = 0;
for(int i=0;i<size;++i) {
int digit = ref.at(i).digitValue();
if(digit<0) {
if(ok) *ok = false;
return 0;
}
value = value*10+digit;
}
if(ok) *ok = true;
return value;
}

mentalmushroom
2nd March 2011, 12:24
yes, but it is boring to create a new function when there is exactly what you need in QString. And yes, in this case it is not very painful, but still it is extra and when used intensively it slows down processing. If QStringRef just had a pointer to a part of the initial string, everything would be ok.

wysota
2nd March 2011, 12:57
It can't have a pointer to a part of the initial string because such thing doesn't exist. QStringRef is the closest you can get to "a part of the initial string". Remember that nobody forces you to use QString. If you only have ascii data, you can use QByteArray. This won't change much as most C functions require the string to end with \0 and there is no \0 in the middle of a string so you'll have to make a copy anyway.