23

I would like to know what is the most efficient and practical way of sending a Qstring as a parameter to a function, in QT more specifically. I want to use a reference. The problem is I also want to instantiate that string in the function itself like so for example:

this is the function prototype:

void myFunction(QString & theMsg);

this is the function call:

myFunction(tr("Hello StringWorld"));

now the function tr() returns a QString but it doesn't work with a reference(I can see why).

I have to do this:

QString theQstr("Hello StringWorld"); 
myFunction(theQstr);

Is there a simpler way to do this while still using references or could I just change the function parameter to use a QString and it would still be efficient?

Julien
  • 1,946
  • 3
  • 33
  • 51
yan bellavance
  • 4,710
  • 20
  • 62
  • 93
  • How about this: myFunction(QString("Hello StringWorld")); – Jamol Jan 21 '10 at 13:10
  • That generated a compile message. I think it is because this only generates a return value without anything concrete to reference to. – yan bellavance Jan 21 '10 at 17:41
  • This link could help: [Right_way_to_pass_QString_to_methods](http://developer.nokia.com/community/wiki/Right_way_to_pass_QString_to_methods) – ABCplus Nov 10 '14 at 11:44
  • Possible duplicate of [How to pass objects to functions in C++?](https://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c) The fact that this question is about `QString` changes nothing about the basic rules of the thumb. – rubenvb May 08 '18 at 11:27

3 Answers3

16

QString uses COW (Copy On Write) behind the scenes, so the actual string isn't copied even if you use a signature like this:

void myFunction(QString theMsg)

(until you modify it that is).

If you absolutely want a reference I would use a const& unless you plan to modify the input argument.

void myFunction(QString const& theMsg)

Morten Fjeldstad
  • 903
  • 2
  • 10
  • 16
  • No thats great, thx! this is what I wanted to know. So it actually does the same thing as an NSString in Objective-C on a mac. – yan bellavance Jan 20 '10 at 20:38
  • 21
    If you look in the Qt source code, you'll see that Qt itself tends to pass Qt types as const T& to functions. Even though they use COW, there is still slightly more overhead in copying a class than just passing a reference. – Colin Jan 21 '10 at 20:42
  • @Colin Can you elaborate on that overhead? I just looked at the source and a QString is just a wrapper around a pointer. I sizeof()ed a `QString` and a `const QString&` to be sure, and both were 4 bytes. Since a QString is basically a pointer itself (and refs are effectively pointers) why would it be more efficient to pass a pointer to a pointer instead of just passing the pointer itself? Sounds like the const-ref would be slightly less efficient... – weberc2 Sep 11 '14 at 17:55
  • @weberc2 I'm not 100% sure about what goes on under the hood in C++, but even if a QString is just a wrapper around a pointer, it seems like there'd be some steps that would need to be taken to figure that out. For example, I'd expect it would need to check for the existence of a copy constructor. Even if there isn't one, or if the copy constructor is just making a copy of the pointer QString wraps, that's still an extra function call. – Colin Sep 13 '14 at 02:49
  • 1
    @Colin The C++ compiler validates the existence of a copy constructor *at compilation time*; this doesn't happen on the fly (c++ is not a dynamic, interpreted language). Moreover, C++ compilers are very, very good at optimizing away function calls. I did some research, and it looks like the overhead is due to the reference-counting, so basically it amounts to an increment operation (incrementing the ref count), a copy op (copying the wrapped pointer), and a comparison op (is the ref count > 0? Do we need to free the pointee?). So yeah, it's a couple of operations bigger... – weberc2 Sep 15 '14 at 21:29
  • @Colin ... but not worth compromising clarity. – weberc2 Sep 15 '14 at 21:30
  • 6
    A copy on write object still has to maintain a pointer to the data and a reference count (atomic increment / decrement) and run through a copy constructor and a destructor. So even if its reasonably efficient it is still more efficient to just pass by reference where you can. It might also make certain inline functions zero-cost if the compiler knows it doesn't have to do anything with the param. – locka Apr 05 '16 at 09:48
10

The most efficient and practical way is using a const reference. The QString COW will be slower than pass by reference but faster than a regular copy.

rpg
  • 7,746
  • 3
  • 38
  • 43
2

When you pass a QString, the call site has to call QString copy ctor then a dtor: both implies an atomic reference counting operation (not neglectable), and some more generated assembly code. Hence slower and bigger code (I don't mention here the less common std::move scenario).

On the other hand, when you pass a const QString&, on the called site, there is a double indirection to access the characters: a pointer to a pointer. Hence this is slower than passing a QString, especially if the QString parameter is much used.

I would recommend to always pass a const QString&, and if you need maximum speed on the called side, make a QString copy there, and access this local copy to avoid a double-indirection (faster, less generated code).

Philippe
  • 422
  • 4
  • 7