[SOLVED] When Ampersand(&) is needed?
hello,
I just saw some code and i can’t understand the usage of the ampersand.
the code that i saw is similar to this,
- //no compile error
the codes that i wrote for expirement
- //no compile error
- //compile error
- //no compile error
and also i saw something like this
- if(item=="hello"){
- ......}
- }
- //no compile error
the code that i wrote,
- if(item=="hello"){
- ......}
- }
- //no compile error
I understand that the something() method that it is a const one,but i can’t understand the “&” usage.Also i can’t understand the difference between the two foreach cases.
In addition no matter which foreach code sample i use my application works correctly.
11 replies
First of all, you need to understand that C++ defines the concept of reference. A simple (lvalue) reference, is identified by an « & ». A reference is just a name for a thing. In other words, a reference defines a synonym for something :
- int a = 10;
- int &ra = a;
Here, ra is a reference. Manipulating ra is the same as manipulating a. Those are two names for the same thing (a literal integer).
With that in mind, let’s now examine those two expressions :
With the second one, each time you send a QString to something, the QString is copied. Thus, this is in fact a copy of the QString that you manipulate inside the function. However, Qt implements what they call « Implicit Sharing » (an other name for « Copy On Write » pattern). Thus, the QString is not entirely copied. Instead datas are just shared among QString instances, until one tries to modify the QString, then a deep copy is made.
However, with the first one, no copy at all is needed. Instead, inside your something function, you are manipulating the same QString object. The reference being qualified as « const », you’re not able to modify this object, because it is in « read only ».
To sum up briefly, the second expression needs to perform a copy, where as the first doesn’t (then the first is better, even with implicit sharing, which is not free).
Here the QString object is also a reference. However, this is not const. If you try to do something like this :
- something("Hello");
- something(myStr);
But then you can expect something to have some side effects, like modifying your QString object.
const here is not really useful, since the string object is a copy. If just may be useful if you want the compiler to raise an error if you try modifying the string object.
So, in C++, to avoid useless copies when passing parameters into function, we use references (identified by an « & »). Generally, those references are const-qualified, to tell the compiler « Hey, I won’t modify this object ». Furthermore, const-reference are able to be bound to temporary objects (like I said before).
lvalue
can you explain to me this term?
the literal string “Hello” (which is of type const char[ 6 ]) will result in a temporary (rvalue)
Are you sure that hello is a const char6???
- const char[] hello = "hello";
- qDebug() << hello[6];
This doesn’t give an ouput.I am almost sure that in c++ arrays count from zero so 5 is 4.
So the meaning of & is a bit different dependig whether used with types or variables.
- //it is used in variables
- QObject obj;
- //it is used in types
correct?
Moreover,
- void startJob(Job &work){
- .....
- delete &work;}
- void doJob(){
- Job *doing = new Job;
- startJob(doing);}
- //no compiler error
In this situation why the pointer is valid?
Is this because of the usage of the ampersand?
- void startJob(Job &work)
In conclusion,after a little search,i found a good article and i understand the reference mechanism.
So the reference is being used in order to avoid copying(making slower) our application.
Is there any reason,for which i should use the reference mech in my functions?
thank you for your help :)
can you explain to me this term?
an lvalue refers to an expression that has a name and persists in memory, as opposite to rvalue which refers to a temporary.
Are you sure that hello is a const char6???
1
2
const char[] hello = “hello”;
qDebug() << hello6;
This doesn’t give an ouput.I am almost sure that in c++ arrays count from zero so 5 is 4.
Yes in fact, this is « const char[ 5 ] ». But I meant the type of “hello” is « const char[ 5 ] », my bad.
EDIT: erf, I was right, you have a final ‘\0’, so this is const char[ 6 ].
I don’t understand what you’re trying to achieve here.
Is there any reason,for which i should use the reference mech in my functions?
anytime you don’t need useless copies.
Anyway, I think you need to take a C++ course before going on with Qt. You can look at the wiki for some good books :)
bq. can you explain to me this term? Yes in fact, this is « const char[ 5 ] ». But I meant the type of “hello” is « const char[ 5 ] »
I can produce an output with const char [5] only with 4 or less.
I don’t understand what you’re trying to achieve here.
I am trying to tell you if understand correctly when the reference is used for memory and when it doesn’t.
Now, If you want to save the copying time, memory, and also don’t want to change the original value, just put ‘const’
And when you ‘call by value’ ,
,Still, Qt is smarter ;), cow [copy on write] comes to action,like its said before.The errors you got , probably because of something in the declaration part, i suppose.
……………………………………………………………………
Interestingly, foreach keyword has something to tell. :) It is a macro and is implemented using the preprocessor. You should go through the docs [doc.qt.nokia.com].
And i think,here again same laws as above.. [ copy / dont copy ]
- if(item=="hello"){
- ......}
- //EDIT:
- if(item=="hello"){
- ......}
- //EDIT : 2
- if(item=="hello"){
- ......}
EDIT 2:
NOTE : Its clear in the document
Qt automatically takes a copy of the container when it enters a foreach loop. If you modify the container as you are iterating, that won’t affect the loop. (If you do not modify the container, the copy still takes place, but thanks to implicit sharing copying a container is very fast.)
Since foreach creates a copy of the container, using a non-const reference for the variable does not allow you to modify the original container. It only affects the copy, which is probably not what you want.
the literal string “Hello” (which is of type const char[ 6 ]) will result in a temporary (rvalue)Are you sure that hello is a const char6???
const char[] hello = "hello"; qDebug() << hello[6];This doesn’t give an ouput.I am almost sure that in c++ arrays count from zero so 5 is 4.
There is a difference between char[] as a type and char[] as an index access.
- const char[] hello = “hello” reserves a consecutive block of memory which stores the characters of the word “hello” at position 0 – 4 and a trailing ‘\0’ at position 5 which terminates strings in C++.
- hello[ 6 ] returns the character stored at position 6 in this consecutive block of memory. Obviously there is none, because the positions range from 0 to 5. Thus you get no output.
So the meaning of & is a bit different dependig whether used with types or variables.
//it is used in variables QObject obj; //it is used in typescorrect?
The idea is right, the code is wrong. The reference operator returns the address of an object, not an object. This address has to be stored in a variable of type “pointer to object”, not “object”. Take another look at the code I’ve posted.
In addition, the pointer has to be of the same type as the object. Otherwise you will have to do an explicit type conversion using a cast (or this is done for you implicitly, as for example in inheritance hierarchies).
Moreover,
void startJob(Job &work){ ..... delete &work;} void doJob(){ Job *doing = new Job; startJob(doing);} //no compiler errorIn this situation why the pointer is valid?
Is this because of the usage of the ampersand?
I don’t think this code compiles.
startJob(Job& work) expects an parameter of type Job, whereas the parameter you pass doing is of type pointer to Job (Job*). That’s two different things, two different types.
Sorry for that comment, Giorgos, but reading this code make me nervous:
- void startJob(Job &work)
- {
- .....
- delete &work;
- }
A reference means you get a reference to an object, but that could be loacted on the stack, the heap or even anywhere else (a const ref also in code segment). If you want to delete some memory by it, I would prefer using pointers as parameters´.
I would prefer here:
- void startJob(Job* work)
- {
- .....
- delete work;
- }
Sorry for that comment, Giorgos, but reading this code make me nervous:
no problem.Comments are more than welcome :)
- void startJob(Job &work)
- {
- .....
- delete &work;
- }
this code is not writen by me.Its just a code that i came across.
I would prefer here:@
void startJob(Job* work)
{ ….. delete work;
}
@
So do I.:)
thank you for your comment
You must log in to post a reply. Not a member yet? Register here!





