C++ : call to temporary is a no-op
-
@JonB said in C++ : call to temporary is a no-op:
Are you aware that (to change the value in a
QSqlRecord
) you are intended to write:
...Yes!
full citation:
class AccountTransactionsTagEntity : public QSqlRecord { //Q_OBJECT public: AccountTransactionsTagEntity(); AccountTransactionsTagEntity(AccountTransactionsTagEntity const &entity); AccountTransactionsTagEntity(AccountTransactionsTagEntity const &&entity) noexcept; explicit AccountTransactionsTagEntity(QSqlRecord const &record); explicit AccountTransactionsTagEntity(QSqlRecord const &&record); [[nodiscard]] int id() const { return field(Id).value().toInt(); } [[nodiscard]] int categorieId() const { return field(CategoryId).value().toInt(); } [[nodiscard]] QString pattern() const { return field(Pattern).value().toString(); } [[nodiscard]] QString description() const { return field(Description).value().toString(); } void setId(int id) { auto f = field(Id); f.setValue(id); replace(Id, f); } // // void setCategorieId(int id) { field(CategoryId).setValue(id); } // void setPattern(QString pattern) { field(Pattern).setValue(pattern); } // void setDescription() { field(Description).value().toString(); } enum Datafield { Id = 0, CategoryId, Pattern, Description }; };
@MasterQ said in C++ : call to temporary is a no-op:
full citation:
You wrote/added this after I wrote about using
QSqlRecord::setValue()
. I am unclear: are you aware that what you show in your "full citation" is not the (best) way to read or write a value in aQSqlRecord
(and you should change)? Just checking.While on the topic you mentioned "isn't everything in Qt a
QObject
" and you are investigating Qt, have you read Implicit Sharing? The list on that page includesQSqlField
(andQSqlRecord
). It is worth understanding this concept in Qt code too. NoQObject
s are implicitly shared. -
Object and QObject are two different things. An object is an instance of a class (c++ basics) , a QObject is a Qt (base) class.
@Christian-Ehrlicher said in C++ : call to temporary is a no-op:
Object and QObject are two different things. An object is an instance of a class (c++ basics) , a QObject is a Qt (base) class.
I never claimed
object
andQObject
are the same thing. I mentioned the doc since @Pl45m4 said QSqlField would be a struct.@JonB said in C++ : call to temporary is a no-op:
@MasterQ said in C++ : call to temporary is a no-op:
full citation:
You wrote/added this after I wrote about using
QSqlRecord::setValue()
. I am unclear: are you aware that what you show in your "full citation" is not the (best) way to read or write a value in aQSqlRecord
(and you should change)? Just checking.I am not sure if I got you. You mean the version to address the field by name is better as to address by index, right? Since I have full controll about the structure of the database I also have full control of the sequence of the fields. I agree that by name is a safer way to do it. Maybe I will change in future. At the moment there are other issues with higher priority.
While on the topic you mentioned "isn't everything in Qt a
QObject
" and you are investigating Qt, have you read Implicit Sharing?No, I was not aware of that topic. Thanks for pointing to.
-
@MasterQ said in C++ : call to temporary is a no-op:
For me it is a difference between altering an object instance and altering the content of an object (instance).
Think about what defines an "object"...
Say you have an object:
Blubb blubb
and a pointer to it:
Blubb *pBlubb = &blubb
In memory:
0x000000 - 0x000004| x | x | x | x | x |
Blubb *pBlubb
could look like this:ptr = 0x000000 (sizeOfBlubb) | | | x | x | x | x | x |
So if you modify the content of your
Blubb
in memory, either via pointer access or change the object itself:| x | x | y | y | y |
the "content" = "instance" changes (what bytes are written to the memory).
What does not change, is the pointer
pBlubb
to yourBlubb
object.... it still points whereBlubb
starts in memory...This is just a simplification, there's much more going on...
I don't understand what you want to tell us with the sentence above ;-)
(Off-topic)
Edit:
Knowing this also helps to understand the difference between:[ 0 ] Blubb *pBlubb; [ 1 ] const Blubb *pBlubb; [ 2 ] Blubb *pBlubb const; [ 3 ] Blubb *const pBlubb; [ 4 ] const Blubb *pBlubb const;
Ask yourself, what can be changed from [0] - [4].
@MasterQ said in C++ : call to temporary is a no-op:
This is by concept of Qt I think. I am wondering why they have decided to return a copy and not a reference to the original field.
Because
QSqlField
is not aQObject
...
It's a registeredQMetaObject
kind of "struct"....
and, as the documentation states, implicitly-shared... so even "copies" share the same memory until you detach them manually or by modifying one of them.@MasterQ said in C++ : call to temporary is a no-op:
No, I was not aware of that topic. Thanks for pointing to.
I explained here already:
@Pl45m4 said in C++ : call to temporary is a no-op:
@MasterQ said in C++ : call to temporary is a no-op:
This is by concept of Qt I think. I am wondering why they have decided to return a copy and not a reference to the original field.
Because QSqlField is not a QObject...
It's a registered QMetaObject kind of "struct"....
and, as the documentation states, implicitly-shared... so even "copies" share the same memory until you detach them manually or by modifying one of them.To sum this up:
QSqlField
is just a data struct, but registered in the meta object system (still not aQObject
).
It contains the column data of a database table (or of the current view on it).
It is implicitly-shared, which means, for 5000 copies of the same record it does not copy the data 5000 times...
Even though they are copies, they share the same data in memory, which means, they are the same until you change something...
Then the modified field detaches and all data is copied, separating the modified field from the others and making it unique.
In memory (your "objects"), you would have 4999 objects which share one memory and for the detached object the data is copied to a new address.And as @aha_1980 said in C++ : call to temporary is a no-op:
Then back to topic: field(0) returns a copy, so calling field(0).setValue(id) modifies the temporary copy.
If I'm not wrong,
setValue(id)
will obviously modify/change the field... which causes the detachment... making a new, temporary field :) -
@Christian-Ehrlicher said in C++ : call to temporary is a no-op:
Object and QObject are two different things. An object is an instance of a class (c++ basics) , a QObject is a Qt (base) class.
I never claimed
object
andQObject
are the same thing. I mentioned the doc since @Pl45m4 said QSqlField would be a struct.@JonB said in C++ : call to temporary is a no-op:
@MasterQ said in C++ : call to temporary is a no-op:
full citation:
You wrote/added this after I wrote about using
QSqlRecord::setValue()
. I am unclear: are you aware that what you show in your "full citation" is not the (best) way to read or write a value in aQSqlRecord
(and you should change)? Just checking.I am not sure if I got you. You mean the version to address the field by name is better as to address by index, right? Since I have full controll about the structure of the database I also have full control of the sequence of the fields. I agree that by name is a safer way to do it. Maybe I will change in future. At the moment there are other issues with higher priority.
While on the topic you mentioned "isn't everything in Qt a
QObject
" and you are investigating Qt, have you read Implicit Sharing?No, I was not aware of that topic. Thanks for pointing to.
@Pl45m4 said in C++ : call to temporary is a no-op:
@MasterQ said in C++ : call to temporary is a no-op:
No, I was not aware of that topic. Thanks for pointing to.
I explained here already:
Because QSqlField is not a QObject...
It's a registered QMetaObject kind of "struct"....
and, as the documentation states, implicitly-shared... so even "copies" share the same memory until you detach them manually or by modifying one of them.This was misleading, sorry. I thought you were talking about the
QSqlField
documentation. But you meant the implicit shared documentation?In the documenation to
QSqlField
implicit sharing is not mentioned.If I'm not wrong,
setValue(id)
will obviously modify/change the field...Yes, you are right! ;-)
-
implicit sharing ... read ... understood ... check!
I now also know, what this suspicious d pointer is.
@MasterQ said in C++ : call to temporary is a no-op:
I now also know, what this suspicious d pointer is.
Haha we shouldn't start to discuss Qt implementation details and strategies here, as the topic is quite a mess already and confusing for future readers :)
The d- and q-pointers have nothing to do with anything here and are a whole new story :)
They are a product of how Qt's internal classes are organized and belong to the pIMPL idiom.@MasterQ said in C++ : call to temporary is a no-op:
In the documenation to QSqlField implicit sharing is not mentioned.
But it is mentioned that
QSqlRecord
andQSqlField
are implicitly shared
Btw: many classes contain that hint... if you know, you know.
And if you read it once, in the future you know right away what you are dealing with :)QSqlField is part of Database Classes and Implicitly Shared Classes.
( https://doc.qt.io/qt-6/qsqlfield.html ) -
@Christian-Ehrlicher said in C++ : call to temporary is a no-op:
Object and QObject are two different things. An object is an instance of a class (c++ basics) , a QObject is a Qt (base) class.
I never claimed
object
andQObject
are the same thing. I mentioned the doc since @Pl45m4 said QSqlField would be a struct.@JonB said in C++ : call to temporary is a no-op:
@MasterQ said in C++ : call to temporary is a no-op:
full citation:
You wrote/added this after I wrote about using
QSqlRecord::setValue()
. I am unclear: are you aware that what you show in your "full citation" is not the (best) way to read or write a value in aQSqlRecord
(and you should change)? Just checking.I am not sure if I got you. You mean the version to address the field by name is better as to address by index, right? Since I have full controll about the structure of the database I also have full control of the sequence of the fields. I agree that by name is a safer way to do it. Maybe I will change in future. At the moment there are other issues with higher priority.
While on the topic you mentioned "isn't everything in Qt a
QObject
" and you are investigating Qt, have you read Implicit Sharing?No, I was not aware of that topic. Thanks for pointing to.
@MasterQ said in C++ : call to temporary is a no-op:
I never claimed object and QObject are the same thing
A QSqlField object can provide some meta-data about the field, ...
meta-data? sounds like QObject.
But you wrote it...
-
M MasterQ has marked this topic as solved on
-
@Christian-Ehrlicher said in C++ : call to temporary is a no-op:
Object and QObject are two different things. An object is an instance of a class (c++ basics) , a QObject is a Qt (base) class.
I never claimed
object
andQObject
are the same thing. I mentioned the doc since @Pl45m4 said QSqlField would be a struct.@JonB said in C++ : call to temporary is a no-op:
@MasterQ said in C++ : call to temporary is a no-op:
full citation:
You wrote/added this after I wrote about using
QSqlRecord::setValue()
. I am unclear: are you aware that what you show in your "full citation" is not the (best) way to read or write a value in aQSqlRecord
(and you should change)? Just checking.I am not sure if I got you. You mean the version to address the field by name is better as to address by index, right? Since I have full controll about the structure of the database I also have full control of the sequence of the fields. I agree that by name is a safer way to do it. Maybe I will change in future. At the moment there are other issues with higher priority.
While on the topic you mentioned "isn't everything in Qt a
QObject
" and you are investigating Qt, have you read Implicit Sharing?No, I was not aware of that topic. Thanks for pointing to.
@MasterQ said in C++ : call to temporary is a no-op:
I am not sure if I got you. You mean the version to address the field by name is better as to address by index, right?
No. I am saying your way of coding, going via a
QSqlField
and commenting on the copying/temporaries etc. is "wrong", at least efficiency-/lines-of-code-wise, for both writing and reading your fields. (Nothing to do with integer indexing vs name indexing, they are just alternatives, integer indexing is faster.) You do not and should not need to accessfield()
at all in either. You simply need:int id() const { return value(Id).toInt(); } void setId(int id) { setValue(Id, id); }
and so on for all your field getters/setters. None of that 3-lines-to-set! Do not go via QSqlRecord::field() at all, forget about
QSqlField
, just use QSqlRecord::value()/setValue().