3

I 'm trying to add testclasses to an existing Qt Project and I came across this question:

void doSomething (QString str, int i) {..}

int main () {
    //Do I use
    doSomething("string", 0);
    //Or
    doSomething(QString("string"), 0);
}

If I'm not mistaken it does the same internally, as it casts the char* implicitly with the QString(char* c) constructor.

But which way is preferred?

I personally like the implicit cast, as it's easier to read than the constructor call, but in my C++ book I read, that implicit casting should be avoided if possible.

msrd0
  • 7,816
  • 9
  • 47
  • 82
Luca Fülbier
  • 2,641
  • 1
  • 26
  • 43
  • maybe it will be usefull: http://stackoverflow.com/questions/12437241/c-always-use-explicit-constructor – Ezee Sep 17 '14 at 14:09
  • Do you actually use other strings (like `std::string') elsewhere ? Are you afraid it is going to be confusing ? "Readability counts" and "Practicality beats purity". Don't overthink it, and don't generalize the answer to this question to other cases. – Félix Cantournet Sep 17 '14 at 14:48
  • `QStringLiteral()` to avoid runtime decoding. – Siyuan Ren Sep 18 '14 at 18:22
  • @Félix QString is used in the whole program. I don't know the pros and cons for String vs QString, as I'm still a beginner. I was just curious, as C++ provides a lot more ways to handle object creation and managing and casts as opposed to Java, which I worked with more. – Luca Fülbier Sep 19 '14 at 00:20
  • QString offer a lot more convenience methods that std::string. It has a split method for instance. If you only use QString, it isn't necessary to explicity create a QString here. – Félix Cantournet Sep 19 '14 at 13:45

3 Answers3

4

Actually if you are using Qt5, the better approach is QStringLiteral(). It not only signifies the intent (a compile time constant QString), but also (slightly) increase efficiency because no runtime conversion from some mulitbyte encoding to UTF-16 is required.

If you need to use Qt4, then conditionally defines it yourself:

#ifndef QStringLiteral
#define QStringLiteral(x) (QString::fromUtf8(x))
#endif

Or as commented by Kuba Ober, add

lessThan(QT_MAJOR_VERSION, 5): DEFINES += QStringLiteral=QString::fromUtf8

to your .pro file.

Quoted from Qt Documentation:

The macro generates the data for a QString out of str at compile time if the compiler supports it. Creating a QString from it is free in this case, and the generated string data is stored in the read-only segment of the compiled object file.

For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to QString::fromUtf8().

If you have code looking like:

 if (node.hasAttribute("http-contents-length")) //... 

One temporary QString will be created to be passed as the hasAttribute function parameter. This can be quite expensive, as it involves a memory allocation and the copy and the conversion of the data into QString's internal encoding.

This can be avoided by doing

if (node.hasAttribute(QStringLiteral("http-contents-length"))) //...

Then the QString's internal data will be generated at compile time and no conversion or allocation will occur at runtime

Using QStringLiteral instead of a double quoted ascii literal can significantly speed up creation of QString's from data known at compile time.

If the compiler is C++11 enabled the string str can actually contain unicode data.

Siyuan Ren
  • 7,573
  • 6
  • 47
  • 61
  • I just looked up QStringLiteral. I thought it was some kind of new class, but it is a makro, right? I'll probably use and comment it shortly, if someone wonders what it does. – Luca Fülbier Sep 19 '14 at 00:23
  • @LucaFülbier: It is a macro that evaluates to some magic, which will in turn statically construct your `QString`. – Siyuan Ren Sep 19 '14 at 03:43
  • Another alternative: add `lessThan(QT_MAJOR_VERSION, 5): DEFINES += QStringLiteral=QString::fromUtf8` to your `.pro` file. – Kuba hasn't forgotten Monica Sep 19 '14 at 16:59
2

Actually in case of Qt the answer is neither. You should use QObject::tr() instead. You may not need translation in every project, but it is much better to have right habit, rather than look through source later and fix it.

If translation of that string is not necessary I recommend to use QString static functions QString::fromAscii(), QString::fromLatin1() or QString::fromLocal8Bit() instead of implicit or explicit cast:

int main () {
    doSomething( QString::fromAscii( "string" ), 0);
}
Slava
  • 43,454
  • 1
  • 47
  • 90
  • The usage of tr() function depends on the context. Usually, I translate only the strings displayed to user, not necessary all the strings in the program. You don't have any information on this kind of context in the question. But the remark is interesting to notice. – Antwane Sep 18 '14 at 17:12
  • I came across tr() too, but didn't use it as it was no user visible string. Are there advantages of using the static functions, or is it for understanding only? – Luca Fülbier Sep 19 '14 at 00:06
0

As you said, if the first parameter of doSomething() method is a QString, the right object will be initialized if you pass a 'const char *', this is more clear, easier to read, and the result is the same.

Your book said you should avoid implicit casting, and it is not a bad advice. In many cases in C++, you will probably be confused by automatic (and hidden) behaviors. But if you write a program using Qt frameworks, you will maybe choose to use QString instead of std::string or char* in most case. I think the implicit conversion is sufficiently explicit and should not cause any trouble in your development.

Antwane
  • 20,760
  • 7
  • 51
  • 84