const-ref when sending signals in Qt

chikuba picture chikuba · May 2, 2012 · Viewed 14.4k times · Source

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?

Answer

Anthony picture Anthony · May 2, 2012

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.