It is not possible to assign an integer value to a reference variable directly, say like:
int &x=10; //not possible
Is there any other way we can modify this statement to make it possible?
But not like this:
int a=10;int &x=a;
This works fine. But I want some other way or modify a little bit my expression and make it work!
The reference as the name says has to reference to something. How do you want to assign a value to it if it doesn't reference anything?
The reason it doesn't work is because 10 is of the type "const int". You can turn that into a reference, but you can't make it non-const without violating some logic at the least.
const int &a = 10;
that'll work.
int &b = const_cast<int &>(static_cast<const int &>(10));
will also compile, but you can't modify b (as that would imply modifying the actual "10" value).
The crux is that 10 is a constant – somewhat obviously: you cannot change its value. But if you try to assign it to an int reference, this would mean that the value were modifiable: an int& is a modifiable value.
To make your statement work, you can use a const reference:
int const& x = 10;
But as “cnicutar” has mentioned in a comment, this is pretty useless; just assign the 10 to a plain int.
You can't bind a reference-to-nonconst to anything immutable.
The standard permits storing compile time constants in ROM (btw, attempting to modify const_cast<>ed compile time constants yields undefined behaviour)
This would basically strip of the const, even if the const is invisible, therefore subverting the whole const-correctness-thing
However, you can bind a reference-to-const to nearly everything, including temporaries:
GotW: A candidate for the most important const
Consider this a "feature".
References refer to objects (perhaps temporary objects), not to values. If you want to store a value somewhere, assign it to an object, not to a reference.
As a special case, const int &a = 10; initializes the reference a to refer to a temporary object with the value 10, and it extends the lifetime of that temporary to the end of the scope of a (12.2/5). That's pretty useless with an integer literal, but occasionally useful with objects of class type. Still, this does not assign an integer value to a reference. It creates a temporary, and binds a reference to the temporary.
in the C++0x, you can use int&& (rvalue references ), but this can be used as function parameter.
Related
When you do this:
int square(int& x) { return x*x;};
int s = square(40); // This gives error
To fix this you do this:
int square(const int& x) { return x*x;};
int s = square(40); // This is OK
I understand that 40 is a constant but so what if I do this:
const int& x = 40
Why would that be okay only with const keyword? Is that the way the compiler protect that no one can change the value referred to by x?
40 is a const so we don't even know its location in memory, but shouldn't the compiler know this address, therefore changing the value from 40 to 30 for example should be allowed since the compiler can just go to address &40 and change the value to 30?
Just because it's possible to implement doesn't mean you should do it. Having 40 really be 30 is hilarious but especially unmaintainable and should not be permitted. In addition, 40 doesn't necessarily actually have an address. Consider a 40 in cache, register, or an immediate instruction.
The declaration of square:
int square(int& x);
takes a lvalue, while invocation of square(40) takes a rvalue, this is inconsistent, see more of lvalue and rvalue here.
The rules about references is that you cannot bind a temporary to non-const lvalue reference. The literal 40 can be used to initialize a temporary but it is, itself, not an object. Thus, you cannot bind a non-const lvalue reference to it.
When you do
int const& value = 40;
you actually bind a temporary object initialized to be 40 to the reference value. Normally, temporaries go out of scope and are destroyed at the end of a full-expression. However, when you directly bind a temporary to a non-const reference its life-time is extended to match the life-time of the reference.
The rules prohibiting binding of temporary objects to non-const references is in place primarily because it would probably cause many surprising results. It could technically be done but would be quite likely to produce non-obvious results.
You're confusing constants and literals. They are similar, but not equivalent. 40 is not a constant, it's a literal.
You can't pass a literal by reference, since if you pass something by reference, it means it can be modified - literals cannot. Consider the following:
void foo(int &i)
{
i = 1;
}
foo(0); // What on Earth? 0 == 1?
If you, however, pass a reference to a constant, it means that even if it's a reference, the function is not permitted to modify its argument (since it's a constant), so now you can safely pass in a literal - it now makes sense, since there's no possibility for the function modifying its argument.
You can still do:
int x = 40;
int s = square(x)
x = 30;
s = square(x);
with both versions of square (the one or without const).
When you pass something by reference you are passing an existing object (because that is what a reference means an alias to an existing object).
In your example:
int s = square(30);
You are NOT passing an object. This is a literal (they are not objects). The compiler can convert literals into object by creating a temporary object. But the language has explicit restrictions on temporary object that mean they are const. This means references can not be passed to an interface where they will be mutated (though you can pass them by const reference).
I'm reading something about overload resolution and I found something that bothers me...In the following code:
int const& MaxValue(int const& a, int const& b)
{
return a > b ? a : b;
}
void SomeFunction()
{
short aShort1 = 3;
short aShort2 = 1;
int const & r2 = MaxValue(aShort1, aShort2); // integral promotion
//is it safe to pass r2 around before function SomeFunction completes
// CallSomeOtherFunctionThatCallsSomethingElse(r2);
}
My understanding is that two temporary int's are created and they're allocated on the stack belonging to SomeFunction.
So when MaxValue returns, r2 referencing to one of those temp variables (in this case, the one that holds value 3).
Thus, is should be safe to pass r2 around.
The question is, if my understanding is fine, is this a standard behavior (please verify)? If not, please explain what is happening in above code.
Many Thanks
Welcome to why implicit casts suck. You now have a reference to a temporary, which has been destroyed. Hope you didn't want to do anything with it.
Yes, your understanding is fine and this is standard behaviour.
Except this:
Thus, is should be safe to pass r2 around.
which I do not understand.
// EDIT
You should use pointers instead of references here to achieve the same but without the problem. Using address of an argument passed by const reference is OK only within the function because it may point to local copy of an object.
Short answer: it is unsafe.
The standard guarantees that a temporary variable can be bound to a constant reference in which case the lifespan of the temporary expands to the lifetime of the bound reference. The problem in your particular case is what reference is actually binding the temporary.
When you call MaxValue( s1, s2 ), two temporary variables of type int are created and bound to the parameter arguments a and b in MaxValue. This means that the lifespan of those temporaries is extended to the completion of the function. Now, in the return statement of your function you are taking a second reference to one of the temporaries and that second reference will not extend the lifetime. r2 will not further extend the lifetime of the object, and you have a dangling reference.
Note that due to the separate compilation, the compiler cannot possibly know from outside of MaxValue whether the returned reference is to one of the arguments or to a completely different object that is not a temporary:
int const & OtherMaxValue( int const & a, int const & b ) {
static int value = 0;
value = (a > b? a : b);
return value;
}
So it cannot possibly guess whether any or which of the temporaries lifetime needs to be extended.
As a side note, for small objects (such as all integer types) passing by reference may be actually worse than passing by value. Also there is already an std::max template that actually implements this functionality.
You should return and pass by value for simple types.
I have been coding in C++ for past few years. But there is one question that I have not been able to figure out. I want to ask, are all temporaries in C++, rvalues?
If no, can anyone provide me an example where temporary produced in the code is an lvalue?
No.
The C++ language specification never makes such a straightforward assertion as the one you are asking about. It doesn't say anywhere in the language standard that "all temporary objects are rvalues". Moreover, the question itself is a bit of misnomer, since the property of being an rvalue in the C++ language is not a property of an object, but rather a property of an expression (i.e. a property of its result). This is actually how it is defined in the language specification: for different kinds of expressions it says when the result is an lvalue and when it is an rvalue. Among other things, this actually means that a temporary object can be accessed as an rvalue as well as an lvalue, depending on the specific form of expression that is used to perform the access.
For example, the result of literal 2 + 3 expression is obviously an rvalue, a temporary of type int. We cannot apply the unary & to it since unary & requires an lvalue as its operand
&(2 + 3); // ERROR, lvalue required
However, as we all know, a constant reference can be attached to a temporary object, as in
const int &ri = 2 + 3;
In this case the reference is attached to the temporary, extending the lifetime of the latter. Obviously, once it is done, we have access to that very same temporary as an lvalue ri, since references are always lvalues. For example, we can easily and legally apply the unary & to the reference and obtain a pointer to the temporary
const int *pi = &ri;
with that pointer remaining perfectly valid as long as the temporary persists.
Another obvious example of lvalue access to a temporary object is when we access a temporary object of class type through its this pointer. The result of *this is an lvalue (as is always the case with the result of unary * applied to a data pointer), yet it doesn't change the fact that the actual object might easily be a temporary. For a given class type T, expression T() is an rvalue, as explicitly stated in the language standard, yet the temporary object accessed through *T().get_this() expression (with the obvious implementation of T::get_this()) is an lvalue. Unlike the previous example, this method allows you to immediately obtain a non-const-qualified lvalue, which refers to a temporary object.
So, once again, the very same temporary object might easily be "seen" as an rvalue or as an lvalue depending on what kind of expression (what kind of access path) you use to "look" at that object.
Prasoon Saurav already linked a very good clc++ thread. In there, James Kanze explains why the question doesn't really make sense. It boils down to:
rvalue-ness is a (boolean) property of expressions - each expression is either an lvalue or an rvalue
temporaries are not expressions
For that reason, the question doesn't make sense.
A good example is the following code:
int main() {
const int& ri = 4;
std::cout << ri << std::endl;
}
The temporary int with value 4 is not an expression. The expression ri that's printed is not a temporary. It's an lvalue, and refers to a temporary.
well, that array operator returns a reference, any function that returns a reference could be considered to do the same thing? all references are const, while they can be lvalues, they modify what they reference, not the reference itself. same is true for the *operator,
*(a temp pointer) = val;
I swear I used to use some compiler that would pass temp values to any function that took a reference,
so you could go:
int Afunc()
{
return 5;
}
int anotherFunc(int & b)
{
b = 34;
}
anotherFunc(Afunc());
can't find one that lets you do that now though, the reference has to be const in order to allow passing of temp values.
int anotherFunc(const int & b);
anyway, references can be lvalues and temporary, the trick being the reference it's self is not modified, only what it references.
if you count the-> operator as an operator, then temporary pointers can be lvalues, but the same condition applies, its not the temp pointer that would be changed, but the thing that it points to.
An array indexing operation is both a temporary and an lvalue, something like a[10] = 1 is an example of what you're looking for; the lvalue is a temporary, calculated pointer.
Short answer: yes, but I'm not going to quote the standard, because proving the point would require addressing every kind of temporary there is. By definition a temporary has a lifetime of one statement, so assigning things to one would be poor style at best.
Interesting answer: Copy elision can make (often makes) a temporary object identical with an lvalue object. For example,
MyClass blah = MyClass( 3 ); // temporary likely to be optimized out
or
return MyClass( 3 ); // likely to directly initialize object in caller's frame
Edit: as for the question of whether there is any temporary object in those cases, §12.8/15 mentions
the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy
which would indicate that there is a temporary object which may be identical with an lvalue.
It depends on what you consider a temporary variable is. You can write something like
#include <stdio.h>
int main()
{
char carray[10];
char *c=carray+1;
*(c+2+4) = 9;
printf("%d\n",carray[7]);
return 0;
}
This runs in VisualStudios and GCC. You can run the code in codepad
I consider (c+2+4) a rvalue although i want to assign to it. When i dereference it, it would become an lvalue. So yes all temporaries are rvalues. But you can make rvalues (thus a temporary) into an lvalue by dereferencing it
If no, can anyone provide me an example where temporary produced in the code is an lvalue?
The following code binds a constant reference to a temporary object of type const float created by the compiler:
int i;
const float &cfr = i;
The behaviour is "as if":
int i;
const float __tmp_cfr = i; // introduced by the compiler
const float &cfr = __tmp_cfr;
What would be better practice when giving a function the original variable to work with:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
or:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: Is there any reason to pick one over another?
My rule of thumb is:
Use pointers if you want to do pointer arithmetic with them (e.g. incrementing the pointer address to step through an array) or if you ever have to pass a NULL-pointer.
Use references otherwise.
I really think you will benefit from establishing the following function calling coding guidelines:
As in all other places, always be const-correct.
Note: This means, among other things, that only out-values (see item 3) and values passed by value (see item 4) can lack the const specifier.
Only pass a value by pointer if the value 0/NULL is a valid input in the current context.
Rationale 1: As a caller, you see that whatever you pass in must be in a usable state.
Rationale 2: As called, you know that whatever comes in is in a usable state. Hence, no NULL-check or error handling needs to be done for that value.
Rationale 3: Rationales 1 and 2 will be compiler enforced. Always catch errors at compile time if you can.
If a function argument is an out-value, then pass it by reference.
Rationale: We don't want to break item 2...
Choose "pass by value" over "pass by const reference" only if the value is a POD (Plain old Datastructure) or small enough (memory-wise) or in other ways cheap enough (time-wise) to copy.
Rationale: Avoid unnecessary copies.
Note: small enough and cheap enough are not absolute measurables.
This ultimately ends up being subjective. The discussion thus far is useful, but I don't think there is a correct or decisive answer to this. A lot will depend on style guidelines and your needs at the time.
While there are some different capabilities (whether or not something can be NULL) with a pointer, the largest practical difference for an output parameter is purely syntax. Google's C++ Style Guide (https://google.github.io/styleguide/cppguide.html#Reference_Arguments), for example, mandates only pointers for output parameters, and allows only references that are const. The reasoning is one of readability: something with value syntax should not have pointer semantic meaning. I'm not suggesting that this is necessarily right or wrong, but I think the point here is that it's a matter of style, not of correctness.
Pointers
A pointer is a variable that holds a memory address.
A pointer declaration consists of a base type, an *, and the variable name.
A pointer can point to any number of variables in lifetime
A pointer that does not currently point to a valid memory location is given the value null (Which is zero)
BaseType* ptrBaseType;
BaseType objBaseType;
ptrBaseType = &objBaseType;
The & is a unary operator that returns the memory address of its operand.
Dereferencing operator (*) is used to access the value stored in the variable which pointer points to.
int nVar = 7;
int* ptrVar = &nVar;
int nVar2 = *ptrVar;
Reference
A reference (&) is like an alias to an existing variable.
A reference (&) is like a constant pointer that is automatically dereferenced.
It is usually used for function argument lists and function return values.
A reference must be initialized when it is created.
Once a reference is initialized to an object, it cannot be changed to refer to another object.
You cannot have NULL references.
A const reference can refer to a const int. It is done with a temporary variable with value of the const
int i = 3; //integer declaration
int * pi = &i; //pi points to the integer i
int& ri = i; //ri is refers to integer i – creation of reference and initialization
You should pass a pointer if you are going to modify the value of the variable.
Even though technically passing a reference or a pointer are the same, passing a pointer in your use case is more readable as it "advertises" the fact that the value will be changed by the function.
If you have a parameter where you may need to indicate the absence of a value, it's common practice to make the parameter a pointer value and pass in NULL.
A better solution in most cases (from a safety perspective) is to use boost::optional. This allows you to pass in optional values by reference and also as a return value.
// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
if (optional_str)
{
cout << *optional_str << std::endl;
}
else
{
cout << "(no string)" << std::endl;
}
}
// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
if (return_nothing)
{
return boost::optional<int>();
}
return boost::optional<int>(42);
}
Use a reference when you can, use a pointer when you have to.
From C++ FAQ: "When should I use references, and when should I use pointers?"
A reference is an implicit pointer. Basically you can change the value the reference points to but you can't change the reference to point to something else. So my 2 cents is that if you only want to change the value of a parameter pass it as a reference but if you need to change the parameter to point to a different object pass it using a pointer.
Consider C#'s out keyword. The compiler requires the caller of a method to apply the out keyword to any out args, even though it knows already if they are. This is intended to enhance readability. Although with modern IDEs I'm inclined to think that this is a job for syntax (or semantic) highlighting.
Pass by const reference unless there is a reason you wish to change/keep the contents you are passing in.
This will be the most efficient method in most cases.
Make sure you use const on each parameter you do not wish to change, as this not only protects you from doing something stupid in the function, it gives a good indication to other users what the function does to the passed in values. This includes making a pointer const when you only want to change whats pointed to...
Pointers:
Can be assigned nullptr (or NULL).
At the call site, you must use & if your type is not a pointer itself,
making explicitly you are modifying your object.
Pointers can be rebound.
References:
Cannot be null.
Once bound, cannot change.
Callers don't need to explicitly use &. This is considered sometimes
bad because you must go to the implementation of the function to see if
your parameter is modified.
A reference is similar to a pointer, except that you don’t need to use a prefix ∗ to access the value referred to by the reference. Also, a reference cannot be made to refer to a different object after its initialization.
References are particularly useful for specifying function arguments.
for more information see "A Tour of C++" by "Bjarne Stroustrup" (2014) Pages 11-12
Consider the following:
int ival = 1.01;
int &rval = 1.01; // error: non-const reference to a const value.
int &rval = ival;
rval = 1.01;
The first assignment of &rval to a literal value fails as expected. If I comment out that line the code compiles and runs. I understand why the initialization fails, but I'm confused why the assignment to rval works in the last line. I didn't think it was allowed to assign a reference to a literal value.
EDIT: Thanks for the quick answers. I'm tempted to delete this to hide my shame, but I think I'll leave it here so everyone else can point and laugh.
In my own defense, I'm working through the exercises in a book (C++ Primer) and this problem is about reference initialization. Still, it's pretty embarrassing to have so completely overlooked the point of a reference in the first place. :)
ival isn't a literal value, 1.01 is the literal value. It's been copied to ival which is a variable, which most definitely can have it's references assigned to another variable.
After the reference is initialized, it is an alias for what it was initialized to. Once a reference is initialized, you cannot change what the reference refers to. However you can change the 'thing' the reference refers to (if the reference is not const).
The last line is in effect setting the variable ival to 1.01 (again).
Here is something you may be surprised to find that you can do though:
const int& x = 42; // No error!
C++ does allow initialising a const reference with a literal value (or other rvalue). What actually happens is that the compiler creates a temporary by copying the RHS, and initialises the reference to refer to that temporary. The compiler ensures that the temporary stays alive until scope exit (i.e whenever x goes out of scope in this case).
Note that this doesn't work when initialising member variables of a class.
Tricky huh? :)