Scope of variables in Qt vs vanilla c++ - c++

Disclaimer: I am total newbie to Qt.
Let's assume we have a byte array returned from a function innerFunc that is later used in another function outerFunc.
QByteArray innerFunc(){
QProcess ls;
ls.start("ls", QStringList() << "-1");
return ls.readAll();
}
void outerFunc(){
QByteArray gotcha = innerFunc();
.
.
.
}
In vanilla c++ I would expect readAll function to return a pointer that needs to be deleted later. In Qt this function returns an instance of the QByteArray class so I guess it shouldn't be accessed outside of the innerFunc's scope.
If so, how should I properly transfer the data to an outer function? Should it copied to QByteArray *tmp = new QByteArray or is it unnecessary?

The code you have looks fine. QByteArray is like std::vector<uint8_t> or std::string and not like a pointer. It manages its own memory. It's fine to return it from a function or pass it to a function by value. The compiler will take care of copying and/or moving the data from one object to another as appropriate, using the contructors/operators defined by the QByteArray class.
QByteArray header file
QByteArray documentation

Related

c++ passing json object by reference

In the below code, I am taking requests from a client, put them together on a json object on my server class and sending it to a pusher(directly connected to a website, putting my data in there so I can search data easily)
The code is working perfectly fine, but my manager said that I need to pass json by reference in this code, and I have no idea what to do.
On Server Class:
grpc::Status RouteGuideImpl::PubEvent(grpc::ServerContext *context,
const events::PubEventRequest *request,
events::PubEventResponse *response){
for(int i=0; i<request->event_size();i++){
nhollman::json object;
auto message = request->events(i);
object["uuid"]=message.uuid();
object["topic"]=message.type();
pusher.jsonCollector(obj);
}
...
}
On Pusher Class:
private:
nholmann::json queue = nlohmann::json::array();
public:
void Pusher::jsonCollector(nlohmann::json dump){
queue.push_back(dump);
}
void Pusher::curlPusher(){
std::string str = queue.dump();
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, str.data());
...
}
As much as I understand, I need to send the json object by reference. How can I do that?
The simple answer is to change
void Pusher::jsonCollector(nlohmann::json dump)
to
void Pusher::jsonCollector(const nlohmann::json& dump)
(note that if this is inside the class then Pusher:: is a non-standard visual studio extension).
This will reduce the number of times the object is copied from 2 to 1 however you can avoid the copy completely by using std::move:
void Pusher::jsonCollector(nlohmann::json dump){
queue.push_back(std::move(dump));
}
And call it with:
pusher.jsonCollector(std::move(obj));
If you want to enforce this behaviour to ensure that callers of jsonCollector always use std::move you can change jsonCollector to:
void Pusher::jsonCollector(nlohmann::json&& dump){
queue.push_back(std::move(dump));
}
Well, references are one of the many, many features, that distinguishes C from C++.
In other languages, like python or java, when you pass an object (not basic types) to a function and change it there, it is changed in the caller entity as well. In these languages, you don't have pointers, but you need to pass the object, not a copy.
That's what you have with references in C++. They are used like value types, but they are no copy.
Pointers can be nullptr (or NULL in C), references cannot. The address a pointer points to can be changed (assigned), you cannot change what object a reference refers to.
Have a look at this https://en.cppreference.com/w/cpp/language/reference for more information.

QString variable changed to QCharRef when i use pointers in method

Hello everyone I am trying to get to know pointers better and I stumbled into a Qt type change. I have made a QString array and gave the pointer to the array to a method. But when I try to use a QString functions it give a error and says that it is a QCharRef which does not have the member function isEmpty().
The code:
QString data_array[2][3] =
{
{"11:28:8","Room 1","Presence detected"},
{"11:38:8","Room 1","No presence"}
}
bool method(QString *_data_array)
{
QString *data_array = _data_array;
return data_array[0][1].isEmpty(); /* changed to QCharRef */
}
My question is why does this happen and how can I prevent it or change it?
The reason for which you are getting QCharRef is due to how QString is built. The [] operator returns one character from a QString (QString is built up from QChars, much like strings in C/C++ are character arrays). From the Qt documentation:
The return value is of type QCharRef, a helper class for QString. When you get an object of type QCharRef, you can use it as if it were a QChar &. If you assign to it, the assignment will apply to the character in the QString from which you got the reference.
So what that means for you is that when you use the lovely square bracket operators, you are no longer using a QString, you are using a QChar reference.
As for how to change it, QChar's isNull() seems like it would fit your uses. so instead try return data_array[0][1].isNull(); and that should work.
I would also look into QStringList if you're doing things with lists of strings

Qt I want to encode a pointer as a string and decode it later

In my Qt app I'd like to encode a pointer to an object as a string, pass it to another bit of code then decode it so that I can access the object.
This is part of internal drag and drop with a QTreeView. In my mimeData() method I have:
QMimeData * TreeModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
foreach (QModelIndex index, indexes)
{
QString colText;
if (index.isValid()) {
TreeItem *item = getItem(index);
// grab the text from each column
for(int cc=0; cc < item->columnCount(); cc++ ) {
colText = item->data(cc).toString();
stream << colText;
}
// add the pointer to the item
qDebug() << quint64(&item);
stream << quint64(&item);
}
}
mimeData->setData("application/vnd.text.list", encodedData);
return mimeData;
}
The qDebug() line produces a number like 140736277471632 which could be right, but is probably wrong.
How should I encode a pointer as a string so that it can be fed into a stream. And how should I then decode it and get the pointer to the original object?
Thank you.
I would dis-advice doing this.
Serializing objects in strings and de-serializing later makes sense for "moving" objects from one process to another. But within one process, you should pass pointers directly, or wrapped in a container like shared-pointer.
If the only way to pass something is a string, create an instance (e.g. QMap<QString, YourPointerType>) where you can register a pointer and access it by a string-name.
If you wrap this map in a class, you can check, if this pointer already exists while registering and if it still exists while retrieving.
Besides, in a models you can store anything you want using User-Roles. You are not limited to store your custom data as mime data.
Here you don't want to take the address of item, but its value. It's a pointer, its value is the address you're looking for, not its address (which, as already mentioned, is completely irrelevant and dangerous to manipulate once the if block scope is exited).
qDebug << qint64(&item);// will print the address this pointer is stored at.
qDebug << qint64(item);// will print the address this pointer is pointing at
EDIT: If you want to get the address back from a string into a pointer, read it as a number from a stringstream, i.e.:
std::istringstream is{str};
long pointer;//be careful with the size of a pointer in your case.
is >> pointer;
TreeItem* item = reinterpret_cast<TreeItem*>(q);

Can't use QString in a QLineEdit nor QComboBox as a parameter

I'm trying to make a function that replace the text inside a QLineEdit when the user want to revert is name to default using a QPushButton.
This is where the code is getting "saved".
`//Must get information in the DB
lineditPlayerName = new QLineEdit("Nouveau Profil");
nameAsDefault = new QString(lineditPlayerName->text());
languageAsDefault = new QString(comboBoxlanguage->currentText());`
This is the function i use to change the value back to default
//This code works
void ProfileManager::revertName(){
lineditPlayerName->setText("nameAsDefault");
btnRevertName->setEnabled(false);
}
But I need it like this :
//This code does'nt
void ProfileManager::revertName(){
lineditPlayerName->setText(NameAsDefault);
btnRevertName->setEnabled(false);
}
I can't get it to work it give's me this error:
no matching function for call to 'QLineEdit::setText(QString*&)'
Thanks
You must dereference the NameAsDefault variable
void ProfileManager::revertName(){
lineditPlayerName->setText(*NameAsDefault);
// ^ Here I dereferenced the pointer
btnRevertName->setEnabled(false);
}
The type of nameAsDefault is pointer to a QString. However QLineEdit::setText expects a QString object, not a pointer. Therefore the compiler tells you that there is no function which expects a pointer.
I did not see your declaration of the nameAsDefault variable, but since
nameAsDefault = new QString(lineditPlayerName->text());
compiles and new returns a pointer, I suppose it is a pointer.
Also, what is probably more important is that you should almost never allocate objects using new. Especially not objects from the Qt library, which are implicitly shared.

how to implement the macros SIGNAL and SLOT as functions QT

Well, what i want is to implement functions that works like the macros SIGNAL and SLOT but with my own implementation, so the goal is that the function (or my own macro if i can create it) receive a parameter like an String "mycustomsignal" and he return a const char* "2mycustomsignal(double,int)" so i do that using a QMap for store this asociation QMap<"signal name","signal signature">, i fill it in another function.
in this case my QMap is this->signals so i search the signature "mycustomsignal(something)" with the key "mycustomsignal" and prepend the code that QObject::connect recognize for signals and i get "2mycustomsignal(something)" so i convert it in const char* because QObject::connect have this parameters in this format and i want to use also in conjuntion with SIGNAL and SLOT MACROS like this:
QObject::connect(customwidget, customwidget->getSignal("somesignal"),
somewidget, SLOT(someslot()));
the function that i use is (only for undertand what i do):
const char* SomeClass::getSignal(QString signalName) {
QString signalsignature = this->signals.value(signalName);
signalsignature.prepend(QString::number(QSIGNAL_CODE));
QByteArray ba = signalsignature.toLatin1();
return signalformated; //Here is the lost of data because QByteArray only exist in the function
}
but this return a pointer to local and the source of the data is destroyed when the function ends, so how i could do this with a function or creating my own MACRO?
Thanks for any help or suggestion.
You have to return QByteArray from your method, return ba;, then get the const char* from the return value:
QObject::connect(customwidget, customwidget->getSignal("somesignal").constData(),
somewidget, SLOT(someslot()));
If you really want to return char pointer, then you have to keep the QByteArray around, for example by adding it to a QList member variable of the same object, so it will get destructed when the instance gets destructed.