33

This is a thing that I never quite got with const-ref and I really hope that someone could explain it to me.

When calling a function inside of another function, I get that const-ref is the best way when passing stack objects that I don't plan to tamper with. For example:

void someInnerFunction(const QString& text) {
    qDebug() << text;
}

void someFunction() {
    QString test = "lala";
    ....
    someInnerFunction(test);
}

So far so good, I guess. But what about signals? Isn't there any risk that comes with passing a reference? Even though it's const. It feels like I've been reading all the docs about const-ref but I still find a bit risky since I understand it as "sending a reference to an object and keeping it const". What if the object it's referring to goes out of scope?

For example:

void someFunction() {
    connect(this, SIGNAL(someSignal(const QString&)), this, SLOT(someSlot(const QString&)));

    QString test = "lala";
    emit someSignal(test);

    // doesnt test go out of scope here? and since im not using queued connection the QString object doesnt get copied. 
}

void someSlot(const QString& test) {
    qDebug() << test; // will this work?
}

What is really happening here? I frequently use const-ref on function calls where I just want to access the object but not change it. But what about signals? Most signals seems to have const-ref parm in the Qt doc, but how does it work?

Null
  • 1,950
  • 9
  • 30
  • 33
chikuba
  • 4,229
  • 6
  • 43
  • 75
  • *"When calling a function inside of another function, I get that const-ref is the best way when passing objects."* That's a very one-size-fits-all answer to a foundational C++ issue, who told you that? – HostileFork says dont trust SE May 01 '12 at 23:56
  • i mean if you dont plan to change them. just seems like qt uses that aproach everywhere and yeah, i dont do it everywhere. but when wuould it not be good? and im only talking about stack-objects where i dont want to copy them to the function – chikuba May 02 '12 at 00:06
  • basically thought that the following discussion was interseting when an stackobject had to be passed as an in-parm. http://stackoverflow.com/questions/270408/is-it-better-in-c-to-pass-by-value-or-pass-by-constant-reference but my question was more what to do with the signals since some ppl state the it should be done by const-ref so that we dont have to copy the object – chikuba May 02 '12 at 00:37
  • 5
    For direct connections, an emitted signal is just syntactic sugar around Qt calling one or more slot functions for you, so it works the same way as a call to a normal C++ method would (except no return values are passed back to the caller, of course). For queued connections, Qt will make a copy of the arguments anyway. – Jeremy Friesner May 02 '12 at 00:46

3 Answers3

26

According to this answer, Qt just replaces const references with copies.

EDIT: Apparently not always the case... I just did a basic test program with one thread, and the reference was passed correctly. Its const-ness remained intact, as well. Anyways, yes, you do need to be wary of the variable going out of scope, plus you can't send references across threads this way. If you do, only copies will be passed.

To answer the questions in the comments of your example, yes, it will work regardless of whether it's a direct or queued connection. If it's a direct connection, it will work because someSlot() will be executed before someFunction() finishes; if it's a queued connection, it will work because test will be copied instead of passed by reference.

Community
  • 1
  • 1
Anthony
  • 8,570
  • 3
  • 38
  • 46
  • 6
    where did you read that? all i saw was "For direct connections, it is recommended that the values are passed by const reference to avoid needless copies. For queued connections Qt will make a copy no matter how you pass the arguments" – chikuba May 01 '12 at 23:52
  • 1
    "Anyways, yes, you do need to be wary of the variable going out of scope" - I don't see where this should be a problem unless you pass objects via pointer. – Frank Osterfeld May 02 '12 at 14:22
  • thanks for putting a lot of effort into you answer and that you kept changing it until you got it right (i hope :p ) – chikuba May 02 '12 at 20:57
  • @jan 2016 seems trolltech.com is defunct. RIP. – linello Jan 18 '16 at 14:46
4

Here is a good demonstration showing how Qt signals/slots manage copying: http://www.embeddeduse.com/2013/06/29/copied-or-not-copied-arguments-signals-slots/

user2449761
  • 1,169
  • 13
  • 25
  • 2
    Citing the conclusion of the provided link may be useful: "_The conclusion [...] is that we should pass arguments to signals and slots by const reference and not by value_" – m7913d Aug 19 '17 at 19:55
0

In Qt, when emitting a signal that is connected to a slot or slots, it equates to a synchronous function call... unless you've configured your signals and slots to use queued connections, then it is an asynchronous call and you should be careful when passing stack data and should pass a copy as if passing data to another thread.

syplex
  • 1,147
  • 6
  • 27
  • 3
    objects passed via const refs are just copied for asynchronous (queued) connections. There is no danger with stack data going out of scope unless you pass them via pointer. – Frank Osterfeld May 02 '12 at 14:18