I saw the following code in plumed and am quite confused:
void ActionAtomistic::makeWhole() {
for(unsigned j=0; j<positions.size()-1; ++j) {
const Vector & first (positions[j]);
Vector & second (positions[j+1]);
second=first+pbcDistance(first,second);
}
}
Could anyone tell me what "&" is used for here? I googled "c++ ampersand between class and variable" but did not find the answer.
Updated: I know what reference is but thought there should not be any space between Vector and "&". Thank you guys for clarifying that.
This means that first is a reference (in this case, a const reference) to an object of type Vector, rather than an object of type Vector.
Read more about references here.
That is known as a reference. I usually write references like Type& name to make it clear that the reference is part of the type.
References are like pointers that are easier to use but come with some restrictions. Here's an example of when you could use a reference:
void add1ToThisNumber(int& num) {
num += 1;
}
// elsewhere...
int myNumber = 3;
add1ToThisNumber(myNumber);
cout << myNumber; // prints 4
A reference (in this case) is basically an alias to another variable. While the following doesn't apply in the first case (as your reference is const), references can be used to modify the objects they are referring to. As an example:
int c = 5;
int& d = c;
d = 12; // c is set to 12
In your particular case, the reference is an immutable alias, so positions[j] cannot be modified through first.
In the second case, doing second = variable will evaluate to positions[j + 1] = variable.
& has different meanings based on context.
Declare a type.
int var;
int& ref1 = var; // Declares a reference to a variable
int const& ref2 = var; // Declares a const reference to a variable
int& foo(); // Declares foo() whose return type is reference to an int
void bar(int&); // Declares bar whose argument type is reference to an int
struct Foo
{
int& bar; // Declares bar to be member variable of the
// class. The type is reference to an int
};
Take address of a variable (any lvalue really)
int var;
int* ptr = &var; // Initializes ptr with the address of var
int arr[4];
int* ptr2 = &(arr[3]); // Initializes ptr2 with the address of the
// last element of arr
Perform bitwise AND operation.
int i = <some value>;
int j = <some value>;
int k = (i & j); // Initializes k with the result of computing
// the bitwise AND of i and j
What you have in your code is the first use.
const Vector & first (positions[j]);
That line declares first to be a const reference to position[j].
Related
I'm new to C++ and learning call by reference now.
I learned this block of code on my material:
void callByRef(&a, &b);
int main(){
int k = 12;
int m = 4;
callByRef(k, m) //QUESTION HERE
return 0;
}
void callByRef(&a, &b){
a += 3;
b -= 2;
return;
}
So my question is when declaring callByRef, we use the addresses of a and b as the parameters, so when we call callByRef in the main, why we need to pass in (k, m) instead of (&k, &m)?
It's basic, but I just want to get the right picture for my future studying.
Thanks guys!
The operator of &a means the address of variable a, the operator of *a means the content of memory addressed by variable a. Now the function definition is following:
void callByRef(int &a, int &b){
a += 3;
b -= 2;
return;
}
where int &a means that a will be a reference to some variable of type int. Therefore whenever you gong to call the function you need to pass the variable itself rather its address, hence callByRef(a, b) and not callByRef(&a, &b).
The reason of such declaration is following, parameters passed to the function, passed by value, namely the content of the variable literally copied into function variable, therefore any change to it inside the function won't have any effect. For example:
void callByVal(int a, int b){
a += 3;
b -= 2;
return;
}
and having:
x = 5;
y = 10;
calling callByVal(x, y) won't have any effect on x and y. To overcome this, you need to pass parameters either by reference or int &a or as an alternative you can pass pointer and update memory directly:
void callByPtr(int *a, int *b){
*a += 3;
*b -= 2;
return;
}
And now it make sense to pass variables addresses, e.g. callByPtr(&a, &b).
The callByRef() function passes the references as arguments so you don't need to send the explicit reference to the function. Have a read through this to understand a bit better.
Tutorial
You don't pass the value. References in C++ aren't exactly like pointers. Think of them as simply being another name for an object.
Naturally you need to bind that name to an object in order for the reference to refer to it. So for instance when we write int &i = k; we are saying that the variable that is already named k, may be referred to as i. To bind the reference, we need to name the other object. And the name of the object is k, not &k.
The same applies to function parameters and arguments. The function callByRef is specified to operate on two objects it will call a and b. When you call that function, you must name the original objects it will refer to. And the original objects are named k and m, not &k and &m.
For example, if F is a reference to an integer, where the reference is not permitted to be pointed to a new object once it is initially pointed to one.
Can I write to declaration like: const int & F?
I am confused about reference and pointer, because they both represent the address of something, but we always write parameter use reference as: const & F, I understand that this is to reduce the copy and does not allow others to change it, but are there any other meanings? and why do we need "const" after a function declaration like: int F(int z) const; this const makes the return type const or everything in the function const?
One more example,
void F(int* p)
{
p+=3;
}
int z=8;
F(&z);
std::cout<<z<<std::endl;
What is the output for z since z is a reference, and I pass it as a pointer who points to an integer.Increasing p by 3 just makes the address different and does not change its value?
Just a first pass at some answers - if anything is unclear please comment and I'll try to elaborate.
int a = 3;
declares an integer, a, with the initial value 3, but you are allowed to change it. For example, later you can do
a = 5; // (*)
and a will have the value 5. If you want to prevent this, you can instead write
const int a = 3;
which will make the assignment (*) illegal - the compiler will issue an error.
If you create a reference to an integer, you are basically creating an alias:
int& b = a;
, despite appearances, does not create a new integer b. Instead, it declares b as an alias for a. If a had the value 3 before, so will b, if you write b = 6 and print the value of a, you will get 6 as well. Just as for a, you can make the assignment b = 6 illegal by declaring it as const:
const int& b = a;
means that b is still an alias for a, but it will not be used to assign a different value to a. It will only be used to read the value of a. Note that a itself still may or may not be constant - if you declared it as non-const you can still write a = 6 and b will also be 6.
As for the question about the pointers: the snippet
void F(int* p) {
p += 3;
}
int z = 8;
F(&z);
does not do what you expected. You pass the address of z into the function F, so inside F, the pointer p will point to z. However, what you are doing then, is adding 3 to the value of p, i.e. to the address that p points to. So you will change to pointer to point at some (semi)random memory address. Luckily, it's just a copy, and it will be discarded. What you probably wanted to do, is increment the value of the integer that p points to, which would be *p += 3. You could have prevented this mistake by making the argument a int* const, meaning: the value of p (i.e. address pointed to) cannot be changed, but the value it points to (i.e. the value of z, in this case) can. This would have made *p += 3 legal but not the "erroneous" (unintended) p += 3. Other versions would be const int* p which would make p += 3 legal but not *p += 3, and const int* const` which would have allowed neither.
Actually, the way you have written F is dangerous: suppose that you expand the function and later you write (correctly) *p += 3. You think that you are updating the value of z whose address you passed in, while actually you are updating the value of a more-or-less random memory address. In fact, when I tried compiling the following:
// WARNING WARNING WARNING
// DANGEROUS CODE - This will probably produce a segfault - don't run it!
void F(int* p) {
p += 3; // I thought I wrote *p += 3
// ... Lots of other code in between, I forgot I accidentally changed p
*p += 3; // NOOOOOOOOOOO!
}
int main()
{
int z=8;
F(&z);
std::cout << z;
return 0;
}
I got a segmentation fault, because I'm writing at an address where I haven't allocated a variable (for all I know I could have just screwed up my boot sector).
Finally, about const after a function declaration: it makes the this pointer a const pointer - basically the compiler emits const A* this instead of just A* this. Conceptually, it states your intention that the function will not change the state of the class, which usually means it won't change any of the (internal) variables. For example, it would make the following code illegal:
class A {
int a;
void f() const {
a = 3; // f is const, so it cannot change a!
}
};
A a;
a.f();
Of course, if the function returns something, this value can have its own type, for example
void f();
int f();
int& f();
const int f();
const int& f();
are functions that return nothing, a (copy of) an integer, a (reference to) an integer, a constant (copy of) an integer, and a constant reference of an integer. If in addition f is guaranteed not to change any class fields, you can also add const after the brackets:
void f() const;
int f() const;
int& f() const;
const int f() const;
const int& f() const;
The way I remember the difference between references and pointers is that a reference must exist and the reference cannot change.
A pointer can be changed, and usually needs to be checked against NULL or tested to verify it points to a valid object.
Also, an object passed by reference can be treated syntactically like it was declared in the function. Pointers must use deferencing syntax.
Hope that helps.
You are confusing things.
First of all int z=8; F(&z); here z IS NOT a reference.
So let me start with the basics:
when found in a type declaration the symbol & denotes a reference, but in any other context, the symbol & means address of.
Similar, in a type declaration * has the meaning of declaring a pointer, anywhere else it it the dereferencing operator, denoting you use the value at an address.
For instance:
int *p : p is a pointer of type int.
x = *p : x is assigned the value found at address p.
int &r = a : r is reference of type int, and r refers the variable a.
p = &a : p is assigned the address of variable a.
Another question you have: the const at the end of a function, like int f(int x) const. This can be used only on non-static class methods and specifies that the function does not modify the object. It has nothing to do with the return value.
I am reading about references in C++. It says that int& a = 5 gives compile time error.
In Thinking in C++ - Bruce Eckel, author says that compiler must first allocate the storage for an int and produce the address to bind to the reference. The storage must be const because changing it would make no sense.
I am confused at this point. I am not able to understand the logic behind it. Why can't be change the content in the storage? I understand that it's invalid as per C++ rules, but why?
"The storage must be const because changing it would make no sense."
If you want a be a reference to a const value, you must declare it as const, because a is referencing to a temporary constant value, and changing it is not possible.
const int &a = 123;
a = 1000; // `a` is referencing to temporary 123, it is not possible to change it
// We can not change 123 to 1000
// Infact, we can change a variable which its value is 123 to 1000
// Here `a` is not a normal variable, it's a reference to a const
// Generally, `int &a` can not bind to a temporary object
For non-const bindings:
int x = 1;
int &a = x;
a is a reference to a lvalue. Simple speaking, it's an alias name for another variable, so on the right hand you should give a variable. The reference a can not change and bind to another variable after it's first binding;
In C++11, you can reference to temporary objects/values by rvalue references:
int &&a = 123;
int& a = 5;
In order for the above code to work, int& needs to bind to a temporary object of type int created out of the expression 5. But binding int& to a temporay didn't appeal to Bjarne Stroustrup — and he gave an example, similar to the following, to illustrate his point:
void f(int &i) { ++i; }
float x = 10.0;
f(x);
std::cout << x <<< std::endl;
What will the std::cout print1? Looks like it will print 11.
It feels, ++i is changing the argument x, but it doesn't. This is one reason why the creator of C++ didn't permit temporaries to bind to non-const reference.
However, you can do this:
int const & i = 10;
int const & j = x; //x is float
And since C++11, you can do this:
int && i = 10;
int && i = x; //x is float
Hope that helps.
1. assuming int& can bind to the temporary created out of x.
What you can do is
int b=5;
int &a=b;
or
const int& a = 5;
suppose I have a function which accept const reference argument pass,
int func(const int &i)
{
/* */
}
int main()
{
int j = 1;
func(j); // pass non const argument to const reference
j=2; // reassign j
}
this code works fine.according to C++ primer, what this argument passing to this function is like follows,
int j=1;
const int &i = j;
in which i is a synonym(alias) of j,
my question is: if i is a synonym of j, and i is defined as const, is the code:
const int &i = j
redelcare a non const variable to const variable? why this expression is legal in c++?
The reference is const, not the object. It doesn't change the fact that the object is mutable, but you have one name for the object (j) through which you can modify it, and another name (i) through which you can't.
In the case of the const reference parameter, this means that main can modify the object (since it uses its name for it, j), whereas func can't modify the object so long as it only uses its name for it, i. func could in principle modify the object by creating yet another reference or pointer to it with a const_cast, but don't.
const int &i = j;
This declares a reference to a constant integer.
Using this reference, you won't be able to change the value of the integer that it references.
You can still change the value by using the original variable name j, just not using the constant reference i.
In a C++ function like this:
int& getNumber();
what does the & mean? Is it different from:
int getNumber();
It's different.
int g_test = 0;
int& getNumberReference()
{
return g_test;
}
int getNumberValue()
{
return g_test;
}
int main()
{
int& n = getNumberReference();
int m = getNumberValue();
n = 10;
cout << g_test << endl; // prints 10
g_test = 0;
m = 10;
cout << g_test << endl; // prints 0
return 0;
}
the getNumberReference() returns a reference, under the hood it's like a pointer that points to an integer variable. Any change applyed to the reference applies to the returned variable.
The getNumberReference() is also a left-value, therefore it can be used like this:
getNumberReference() = 10;
Yes, the int& version returns a reference to an int. The int version returns an int by value.
See the section on references in the C++ FAQ
Yes, it's different.
The & means you return a reference. Otherwise it will return a copy (well, sometimes the compiler optimizes it, but that's not the problem here).
An example is vector. The operator[] returns an &. This allows us to do:
my_vector[2] = 42;
That wouldn't work with a copy.
The difference is that without the & what you get back is a copy of the returned int, suitable for passing into other routines, comparing to stuff, or copying into your own variable.
With the &, what you get back is essentially the variable containing the returned integer. That means you can actually put it on the left-hand side of an assignment, like so:
getNumber() = 200;
The first version allows you to write getNumber() = 42, which is probably not what you want. Returning references is very useful when overloading operator[] for your own containers types. It enables you to write container[9] = 42.
int& getNumber(): function returns an integer by reference.
int getNumber(): function returns an integer by value.
They differ in some ways and one of the interesting differences being that the 1st type can be used on the left side of assignment which is not possible with the 2nd type.
Example:
int global = 1;
int& getNumber() {
return global; // return global by reference.
}
int main() {
cout<<"before "<<global<<endl;
getNumber() = 2; // assign 2 to the return value which is reference.
cout<<"after "<<global<<endl;
return 0;
}
Ouptput:
before 1
after 2
"&" means reference, in this case "reference to an int".
It means that it is a reference type. What's a reference?
Wikipedia:
In the C++ programming language, a reference is a simple reference datatype that is less powerful but safer than the pointer type inherited from C. The name C++ reference may cause confusion, as in computer science a reference is a general concept datatype, with pointers and C++ references being specific reference datatype implementations. The declaration of the form:
Type & Name
where is a type and is
an identifier whose type is reference
to .
Examples:
int A = 5;
int& rA = A;
extern int& rB;
int& foo ();
void bar (int& rP);
class MyClass { int& m_b; /* ... */ };
int funcX() { return 42 ; }; int (&xFunc)() = funcX;
Here, rA and rB are of type "reference
to int", foo() is a function that
returns a reference to int, bar() is a
function with a reference parameter,
which is reference to int, MyClass is
a class with a member which is
reference to int, funcX() is a
function that returns an int, xFunc()
is an alias for funcX.
Rest of the explanation is here
It's a reference
It means it's returning a reference to an int, not an int itself.
It's a reference, which is exactly like a pointer except you don't have to use a pointer-dereference operator (* or ->) with it, the pointer dereferencing is implied.
Especially note that all the lifetime concerns (such as don't return a stack variable by address) still need to be addressed just as if a pointer was used.