I understand the reference variable concept. It's an alias to the other variable.
int varA = 100;
int &varB = varA;
Here varB is a referring to varA, both pointing to same memory location. Changes to one variable reflect in the other.
Question:
a) int &c = 100;
What is the meaning of the above statement, and how does it differ from the following?
b) int c = 100;
Is there any scenario where we need to use 1(a) rather than 1(b)?
All are correct, except this:
int &c = 100; //error
It will give compilation error both in C++03, and C++11. It is because it attempts to bind non-const reference to a temporary object (created out of 100) which is disallowed.
In C++11, you could do this, however:
int && c = 100; //ok
It is called rvalue-reference.
You could bind const reference to a temporary though (both in C++03, and C++11):
int const & c = 100;
-
int c = 100;
It simply defines an object called c and initializes it with 100. No reference here.
int &c = 100
is invalid code, you cannot bind a non-const reference to a temporary.
To make it valid, you need a const reference:
const int &c = 100;
While,
int c = 100
is a valid code. It creates a variable named c of the type int and initializes it with 100.
1) int& c = 100; is illegal, whereas the second one is not.
I understood the reference variable concept.
If you really understood references, are you expecting that after you do c = 101 the constant 100 suddenly turns to 101?
2) No point in answering, since 1) is illegal.
int& i = 100;
Is illegal.
It is legal to say:
int const& i = 100;
const int& i = 100; // same as above
Not particularly useful in this context, but it needs to work for the purposes of function calls:
void foo(int const& i) { ... }
...
foo(100);
Related
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].
I am little confused with the return type of const_cast? Does the type inside the angular brackets <> is the return type?
const int i = 5;
int b = const_cast<int&>(i);
Is const_cast returning int& (integer reference), if yes then why how we storing it in integer? Or we should modify the code to:
const int i = 5;
int & b = const_cast<int&>(i);
Yes. But instead of returning you should say that the type of the resulting expression is the type in <>.
When that type is a reference, as in const_cast<int&>, it means that it is a l-value. In the first case there is no difference, as it is immediately converted to an r-value anyway. But then, the const in such an r-value is ignored, so:
int b = const_cast<int&>(i); //ok
int b = const_cast<int>(i); //also ok
int b = i; //hey! also ok
In the second case there is a difference, because there is no l-value to r-value conversion:
int &b = const_cast<int&>(i); //ok
int &b = const_cast<int>(i); //error: cannot bind a reference to an r-value
int &b = i; //error: cannot bind a `int&` to a `const int&`
Does const_cast return the type specified inside angular bracket
It evaluates to an expression of the type in the angular brackets. What matters here is how you use that expression:
const int i = 5;
int b = const_cast<int&>(i);
In this case, b is just a copy of i. The cast is not required.
const int i = 5;
int & b = const_cast<int&>(i);
Here, b refers to i. Note that using it to modify the value of i is undefined behaviour.
Does the type inside the angular brackets <> is the return type?
Yes, the return type of const_cast<int&>(i) is int&. After that you assign it to a int, and the value get copied.
And in int & b = const_cast<int&>(i);, you assign it to a int&, now b is the reference to i. Pay attention to that any modification on b will cause undifined behaviour.
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;
In the following, would there be a temporary object created before const reference is used to a non-const object?
const int y = 2000;
const int &s = y // ok, const reference to const object.
int x = 1000;
const int &r = x; // any temporary copy here?
If no then, how does this work?
const int z = 3000;
int &t = z // ok, why can't you do this?
No.
A reference is simply an alias for an existing object. const is enforced by the compiler; it simply checks that you don't attempt to modify the object through the reference r.* This doesn't require a copy to be created.
Given that const is merely an instruction to the compiler to enforce "read-only", then it should be immediately obvious why your final example doesn't compile. const would be pointless if you could trivially circumvent it by taking a non-const ref to a const object.
* Of course, you are still free to modify the object via x. Any changes will also be visible via r, because they refer to the same object.
In
int x = 1000;
const int &r = x;
the right-hand side is an lvalue and the type of x is the same as the type of the reference (ignoring cv-qualifications). Under these circumstances the reference is attached directly to x, no temporary is created.
As for "how does this work"... I don't understand what prompted your question. It just works in the most straighforward way: the reference is attached directly to x. Nothing more to it.
You can't do
const int z = 3000;
int &t = z;
because it immediately violates the rules of const-correctness.
The understanding on the Reference (&) answers this question..
Reference is just an alias to the variable that it is assigned to it..
And const is a constraint imposed by the compiler to the variable that is declared as const
int x = 1000;
const int &r = x;
In this case, its a const reference to a non const variable. So you cannot change the data of x with reference variable r(just acts a read only).. yet you can still change the data x by modifying x
const int z = 3000;
int &t = z
In this case, non const reference to const member which is meaningless. You are saying reference can allow you to edit a const member(which is never possible)..
So if you want to create a reference for a const member, it has to be like the first case you mentioned
const int z = 3000;
const int &t = z;
int main(){
int x = 10;
const int&z = x;
int &y = z; // why is this ill formed?
}
Why is initializing non constant reference to int to a constant reference not correct? What is the reason behind this?
Well, why shouldn't it be ill-formed?
It is ill-formed because it breaks the obvious rules of const correctenss. In C++ language you are not allowed to implicitly convert the constant access pass to a non-constant access path. It is the same for pointers and for references. That's the whole purpose of having constant access paths: to prevent modification of the object the path leads to. Once you made it constant, you are not allowed to go back to non-constant, unless you make a specific explicit and conscious effort to do that by using const_cast.
In this particular case you can easily remove the constness from the access path by using const_cast (this is what const_cast is for) and legally modify the referenced object, since the referenced object is not really constant
int main(){
int x = 10;
const int &z = x;
int &y = const_cast<int &>(z);
y = 42; // modifies x
}
Since y isn't const, you would be able to write y = 42 and change z (which is const) too.
Because a const reference is unmodifiable, while a standard reference is.
The compiler assumes that the thing referred to by a const int & is a const int, even though in this case it isn't. You cannot make a non-const reference refer to a const int, because you would then be able to change the (notionally) const int via the reference.
Because
int const x = 10;
int const& z = x;
int& y = z;
y = 42;
would modify a constant variable.
As others say, it would allow one to indirectly change x, which breaks the const-correctness promise. See http://en.wikipedia.org/wiki/Const_correctness