Copying overhead
Both of these methods will copy data from the input string into the class variable:
QString name; //member variable of TestClass class
void TestClass::setName1(const QString & name) {
this->name = name;
}
void TestClass::setName2(const QString name) {
this->name = name;
}
In the second one, a copy of the QString will be made on the stack first. You are correct to think that pass-by-value causes more copy overhead. This is the reason pass-by-value is generally discouraged for classes that contain a lot of data.
See this question for more discussion of pass-by-reference vs. pass-by-value.
However, in this specific example, the difference in overhead is very small: QString uses implicit sharing. When you copy QString (e.g. with operator=), it simply creates another reference to the same data. So just copying a QString — even a very long one — isn't substantively more intensive than copying a reference.
Dangling references
Foo(Bar &bar) : bar(bar) { }
Bar &bar; //member variable of Foo class
This code can, indeed, cause problems if the original bar
is deleted while your Foo
class is still around (this is known as a "dangling reference"). Using references in this manner is a lot like using pointers: it's up to you as the programmer to make sure all objects involved manage memory correctly.
If you're concerned about dangling pointers/references in your Qt application, try QPointer:
A guarded pointer, QPointer, behaves like a normal C++ pointer T *, except that it is automatically set to 0 when the referenced object is destroyed (unlike normal C++ pointers, which become "dangling pointers" in such cases). T must be a subclass of QObject.
You could rewrite the code above like this:
Foo(Bar * bar) : bar(bar) { }
QPointer<Bar> bar; //member variable of Foo class
Then you are partially protected from dangling pointer errors:
Bar * myBar = new Bar();
Foo myFoo(myBar); // myFoo->bar is set to myBar
delete myBar; // myFoo->bar becomes 0
As long as your class methods check this->bar
for null before using it, you can avoid operating on uninitialized memory. (Or, if you don't, you'll get a segmentation fault pretty quickly, instead of potentially more subtle undefined behavior from accessing an already-deleted address.)