double& (not passing by reference) C++ - c++

typedef double real8;
typedef real8 Real_t;
Real_t& x(int y);
What is Real_t& ?? I've only seen a datatype followed by "&" to indicate pass by reference.
But this is in declaration line. What does this mean ?

This means that the function returns a reference to a Real_t which is actually a double. The Real_t is a real8 which is a double if you resolve all the typedefs.
You should be careful here. If the result being passed by reference isn't retrieved from a scope that exists pasts the end of the function, then you'll have a dangling reference.
For example:
int& foo() {
int x = 8;
return x;
}
int main() {
int y = foo();
}
The variable, y, in main ends up referring to a variable which has been destroyed as it went out of scope when foo() returned, so using it is undefined behavior. If x had been retrieved from a singleton or something that lives outside the scope of the function foo(), then it would still exist though and this would be fine.
People sometimes return references to initialize static globals in a deterministic way between compilation units, so you might see this used with statics like:
MyClass& MyStaticVar() {
static MyClass instance;
return instance;
}
Which is also okay, because the static lives for the duration of the program after initialized.

It means x is a function that returns a reference to a Real_t.
An example of returning by reference is for data access in classes. For example, std::vector::at() returns a reference to an element of the vector.
For a free function to safely return a reference, there must be something non-obvious going on inside the function to ensure that a dangling reference isn't returned.

Related

How do constant references work?

Recently I have been learning about good programming practice in C++ and found out that many programs pass objects to functions by reference so that multiple instances are not created. I have also learned that passing a constant reference prevents the original object from being modified however I do not understand how this works exactly. Shouldn't a constant reference create a new instance because the original object cannot be modified through the reference but the reference can still be used like a separate object? I'm fairly certain that this is not how it works but then, how does it work? Is there something I missed?
I have also learned that passing a constant reference prevents the original object from being modified [...]
Not quite. You are not allowed to modify the object through the const &. In other words, you have read-only access. But nothing natively prevents other code with read-write access (for example the original owner of the referred object) to modify it. You do need to be careful when designing so that such changes do not surprise you.
A constant reference (const&) is similar to a pointer to a constant object. You are allowed to read it through the reference but not modify it. Others, holding a non-const reference can still modify it.
Shouldn't a constant reference create a new instance because the
original object cannot be modified through the reference but the
reference can still be used like a separate object?
It's better to call it a reference to a constant object. This makes it much clearer how the thing works. Calling it the other way around is just confusing because any reference is constant (meaning you can't let it refer to another object after initialization).
So a reference to a constant object is just an additional name for an existing object (like a non-const reference) with the restriction that this name only allows reading from the existing object.
This means that through a reference to a constant object you can:
only read from member variables of the object, but not assign to them, unless a member is marked as mutable
only call methods of the object that are marked as const
Example:
struct Foo
{
int a;
mutable int b;
void SetA( int newA ) { a = newA; }
int GetA() const { return a; }
};
void DoSomething( const Foo& f )
{
// Here, f is just another name for foo, but it imposes some restrictions:
f.a = 42; // compiler error, can't modify member!
f.SetA( 42 ); // compiler error, can't call non-const method!
int x = f.a; // OK, reading is allowed.
f.b = 42; // OK, because b is marked as mutable
int y = f.GetA(); // OK, because GetA() is marked as const
}
int main()
{
Foo foo;
DoSomething( foo );
}

Returning const reference

I'm somewhat confused about the declaration of functions returning const references to temporaries.
In the following code
#include <string>
#include <iostream>
using namespace std;
const string& foo() {
return string("foo");
}
string bar() {
return string("bar");
}
int main() {
const string& f = foo();
const string& b = bar();
cout << b;
}
What is the difference between methods foo and bar ?
Why does foo give me warning: returning reference to local temporary object [-Wreturn-stack-address]. Isn't a copy of the temporary created on const string& f = foo(); ?
string("foo") creates an object of type std::string containing the value "foo" locally in the function. This object will be destroyed at the end of the function. So returning the reference to that object will be invalid once the code leaves that function [1]. So in main, you will never have a valid reference to that string. The same would be true if you created a local variable inside foo.
The WHOLE point of returning a reference is that you don't make a copy, and initializing a reference (string &f = foo() is an initialization) will not create a copy of the original object - just another reference to the same object [which is already invalid by the time the code is back in main]. For many things, references can be seen as "a different name for the same thing".
The lifetime of the referred object (in other words, the actual object the "alias name" refers to) should ALWAYS have a lifetime longer than the reference variable (f in this case).
In the case of bar, the code will make a copy as part of the return string("bar");, since you are returning that object without taking its reference - in other words, by copying the object, so that works.
[1] pedantically, while still inside the function, but after the end of the code you have written within the function, in the bit of code the compiler introduced to deal with the destruction of objects created in the function.
Isn't a copy of the temporary created on const string& f = foo();
Where did you hear that?
Adding const to a reference often allows the lifetime of a temporary with which it's been initialised to be extended to the lifetime of the reference itself. There's never a copy.
Even that's not the case here, though. The object you're binding to the reference goes out of scope at the end of the function and that takes precedence over everything else.
You're returning a dangling reference; period.
Why does foo give me warning: returning reference to local temporary
object [-Wreturn-stack-address].
You are creating a temporary string object inside foo(), and you are returning a reference to that object which will immediately go out of scope (dangling reference).
const string& foo() {
return string("foo"); // returns constant reference to temporary object
} // object goes out of scope
bar() is quite different:
string bar() {
return string("bar"); // returns a copy of temporary string
}
...
const string& b = bar(); // reference an rvalue string
What is the difference between methods foo and bar ?
foo() returns a constant (dangling) reference while bar() returns a copy of a temporary string object.
In both of the cases, a string object is initialized and allocated on the stack.
After returning from the function, the memory segment which contains it becomes irrelevant, and its content may be overridden.
The difference between the functions:
bar function return a copy of the string instance which is created inside it.
foo function returns a reference to the string instance which is created inside it.
In other words, it returns an implicit pointer to its return value, which resides in a temporary memory segment - and that's the reason for your warning.

Is there a way of safely pointing to a temporary value declared inside of a function?

Consider the following code:
int * p;
void Set()
{
int i = 7;
p = & i; // potentially disastrous
}
I know that pointing to a value that may be overwritten is bad but I recall reading that there was a way to prevent a value such as i from being lost when declared and then pointed to in this way. I've scoured my text book but have had trouble finding the exact text elaborating on this and am starting to think I may have even imagined it. Is there a way of safely pointing to a temporary value declared inside of a function? A way of making the temporary value i no longer temporary?
Thanks for all your help in advance!
I recall reading that there was a way to prevent a value such as i from being lost when declared and then pointed to in this way
The closest thing to what you mention (if I understood your sentence correctly) is the rule which allows prolonging the lifetime of a temporary when bound to a reference (§ 12.2/5 of the C++11 Standard):
struct X { int x = 0; };
X foo() { return X(); }
int main()
{
X const& x = foo(); // The lifetime of the object bound to x is prolonged
x.x = 42; // This is OK
}
However, there is no such rule for pointers nor for objects that are not temporaries.
A way of making the temporary value i no longer temporary?
In your example, i is not a temporary: it is an object with automatic storage duration. A temporary is an object whose life-time (usually) terminates at the end of the full expression that creates it (with the exception mentioned above and a few more listed in § 12.2/4-5).
taking const ref to an temporary extends liifetime of this temporary up to the end of scope of this const reference, however in your example you are not taking address of temporary but local automatic object i.
so to extends lifetime of temporary do simply:
const int& iref=int(3);
int a= iref;
//..do stuff with iref, i.e:
printf("iref: %d\n", a);
output:
iref: 3
RUN SUCCESSFUL (total time: 46ms)
The value of i has to reside in memory somewhere. If you declare it inside a function, it is likely to be allocated on the stack and will be lost when the function returns. If you really need the value to always be constant like in your example, then what you need is to declare it outside the function as static const:
int * p;
static const int i = 7;
void Set()
{
p = & i;
}
If this is not what you need, maybe you can elaborate a bit on your very minimal example code so that we can better understand what you are trying to achieve.
you can use the static keyword.
#include <stdio.h>
int *p;
void set() {
static int x = 7;
p = &x;
}
int main(){
set();
printf("%d", *p);
}
correctly prints 7.
however, I would strongly discourage using such a piece of code in anything but a research on the static keyword and pointers.

method result declared by value, implementation by reference valid?

I have been wondering if it is valid c++ if I return something from a method by reference, while the method is actually declared to return by value:
class A {
public:
int method(){
int i = 123;
int& iref = i;
return iref;
}
};
This compiles fine and seems to work. From what I understand this should return by value, as declared in the method's signature. I do not want to end up returning a reference to the local variable. Does anyone know if this is 'proper c++ code' without traps?
This is a perfectly valid C++ code and does exactly what you expect it to do:
Have a local variable
Have a local reference to that local variable
Make a copy of the variable referenced to by your local reference
Return that copy to a caller (unwind stack, destroying both local variable and a reference to it)
Don't worry, you will not end up returning a reference to a local variable this way.
The code is fine, it will return an int by value with the value of i.

Which are the implications of return a value as constant, reference and constant reference in C++?

I'm learning C++ and I'm still confused about this. What are the implications of return a value as constant, reference and constant reference in C++ ? For example:
const int exampleOne();
int& exampleTwo();
const int& exampleThree();
Here's the lowdown on all your cases:
• Return by reference: The function call can be used as the left hand side of an assignment. e.g. using operator overloading, if you have operator[] overloaded, you can say something like
a[i] = 7;
(when returning by reference you need to ensure that the object you return is available after the return: you should not return a reference to a local or a temporary)
• Return as constant value: Prevents the function from being used on the left side of an assignment expression. Consider the overloaded operator+. One could write something like:
a + b = c; // This isn't right
Having the return type of operator+ as "const SomeType" allows the return by value and at the same time prevents the expression from being used on the left side of an assignment.
Return as constant value also allows one to prevent typos like these:
if (someFunction() = 2)
when you meant
if (someFunction() == 2)
If someFunction() is declared as
const int someFunction()
then the if() typo above would be caught by the compiler.
• Return as constant reference: This function call cannot appear on the left hand side of an assignment, and you want to avoid making a copy (returning by value). E.g. let's say we have a class Student and we'd like to provide an accessor id() to get the ID of the student:
class Student
{
std::string id_;
public:
const std::string& id() const;
};
const std::string& Student::id()
{
return id_;
}
Consider the id() accessor. This should be declared const to guarantee that the id() member function will not modify the state of the object. Now, consider the return type. If the return type were string& then one could write something like:
Student s;
s.id() = "newId";
which isn't what we want.
We could have returned by value, but in this case returning by reference is more efficient. Making the return type a const string& additionally prevents the id from being modified.
The basic thing to understand is that returning by value will create a new copy of your object. Returning by reference will return a reference to an existing object. NOTE: Just like pointers, you CAN have dangling references. So, don't create an object in a function and return a reference to the object -- it will be destroyed when the function returns, and it will return a dangling reference.
Return by value:
When you have POD (Plain Old Data)
When you want to return a copy of an object
Return by reference:
When you have a performance reason to avoid a copy of the object you are returning, and you understand the lifetime of the object
When you must return a particular instance of an object, and you understand the lifetime of the object
Const / Constant references help you enforce the contracts of your code, and help your users' compilers find usage errors. They do not affect performance.
Returning a constant value isn't a very common idiom, since you're returning a new thing anyway that only the caller can have, so it's not common to have a case where they can't modify it. In your example, you don't know what they're going to do with it, so why should you stop them from modifying it?
Note that in C++ if you don't say that something is a reference or pointer, it's a value so you'll create a new copy of it rather than modifying the original object. This might not be totally obvious if you're coming from other languages that use references by default.
Returning a reference or const reference means that it's actually another object elsewhere, so any modifications to it will affect that other object. A common idiom there might be exposing a private member of a class.
const means that whatever it is can't be modified, so if you return a const reference you can't call any non-const methods on it or modify any data members.
Return by reference.
You can return a reference to some value, such as a class member. That way, you don't create copies. However, you shouldn't return references to values in a stack, as that results in undefined behaviour.
#include <iostream>
using namespace std;
class A{
private: int a;
public:
A(int num):a(num){}
//a to the power of 4.
int& operate(){
this->a*=this->a;
this->a*=this->a;
return this->a;
}
//return constant copy of a.
const int constA(){return this->a;}
//return copy of a.
int getA(){return this->a;}
};
int main(){
A obj(3);
cout <<"a "<<obj.getA()<<endl;
int& b=obj.operate(); //obj.operate() returns a reference!
cout<<"a^4 "<<obj.getA()<<endl;
b++;
cout<<"modified by b: "<<obj.getA()<<endl;
return 0;
}
b and obj.a "point" to the same value, so modifying b modifies the value of obj.a.
$./a.out
a 3
a^4 81
modified by b: 82
Return a const value.
On the other hand, returning a const value indicates that said value cannot be modified. It should be remarked that the returned value is a copy.:
For example,
constA()++;
would result in a compilation error, since the copy returned by constA() is constant. But this is just a copy, it doesn't imply that A::a is constant.
Return a const reference.
This is similiar to returning a const value, except that no copy is return, but a reference to the actual member. However, it cant be modified.
const int& refA(){return this->a;}
const int& b = obj.refA();
b++;
will result in a compilation error.
const int exampleOne();
Returns a const copy of some int. That is, you create a new int which may not be modified. This isn't really useful in most cases because you're creating a copy anyway, so you typically don't care if it gets modified. So why not just return a regular int?
It may make a difference for more complex types, where modifying them may have undesirable sideeffects though. (Conceptually, let's say a function returns an object representing a file handle. If that handle is const, the file is read-only, otherwise it can be modified. Then in some cases it makes sense for a function to return a const value. But in general, returning a const value is uncommon.
int& exampleTwo();
This one returns a reference to an int. This does not affect the lifetime of that value though, so this can lead to undefined behavior in a case such as this:
int& exampleTwo() {
int x = 42;
return x;
}
we're returning a reference to a value that no longer exists. The compiler may warn you about this, but it'll probably compile anyway. But it's meaningless and will cause funky crashes sooner or later. This is used often in other cases though. If the function had been a class member, it could return a reference to a member variable, whose lifetime would last until the object goes out of scope, which means function return value is still valid when the function returns.
const int& exampleThree();
Is mostly the same as above, returning a reference to some value without taking ownership of it or affecting its lifetime. The main difference is that now you're returning a reference to a const (immutable) object. Unlike the first case, this is more often useful, since we're no longer dealing with a copy that no one else knows about, and so modifications may be visible to other parts of the code. (you may have an object that's non-const where it's defined, and a function that allows other parts of the code to get access to it as const, by returning a const reference to it.
Your first case:
const int exampleOne();
With simple types like int, this is almost never what you want, because the const is pointless. Return by value implies a copy, and you can assign to a non-const object freely:
int a = exampleOne(); // perfectly valid.
When I see this, it's usually because whoever wrote the code was trying to be const-correct, which is laudable, but didn't quite understand the implications of what they were writing. However, there are cases with overloaded operators and custom types where it can make a difference.
Some compilers (newer GCCs, Metrowerks, etc) warn on behavior like this with simple types, so it should be avoided.
I think that your question is actually two questions:
What are the implications of returning a const.
What are the implications of returning a reference.
To give you a better answer, I will explain a little more about both concepts.
Regarding the const keyword
The const keyword means that the object cannot be modified through that variable, for instance:
MyObject *o1 = new MyObject;
const MyObject *o2 = o1;
o1->set(...); // Will work and will change the instance variables.
o2->set(...); // Won't compile.
Now, the const keyword can be used in three different contexts:
Assuring the caller of a method that you won't modify the object
For example:
void func(const MyObject &o);
void func(const MyObject *o);
In both cases, any modification made to the object will remain outside the function scope, that's why using the keyword const I assure the caller that I won't be modifying it's instance variables.
Assuring the compiler that a specific method do not mutate the object
If you have a class and some methods that "gets" or "obtains" information from the instance variables without modifying them, then I should be able to use them even if the const keyword is used. For example:
class MyObject
{
...
public:
void setValue(int);
int getValue() const; // The const at the end is the key
};
void funct(const MyObject &o)
{
int val = o.getValue(); // Will compile.
a.setValue(val); // Won't compile.
}
Finally, (your case) returning a const value
This means that the returned object cannot be modified or mutated directly. For example:
const MyObject func();
void func2()
{
int val = func()->getValue(); // Will compile.
func()->setValue(val); // Won't compile.
MyObject o1 = func(); // Won't compile.
MyObject o2 = const_cast<MyObject>(func()); // Will compile.
}
More information about the const keyword: C++ Faq Lite - Const Correctness
Regarding references
Returning or receiving a reference means that the object will not be duplicated. This means that any change made to the value itself will be reflected outside the function scope. For example:
void swap(int &x, int &y)
{
int z = x;
x = y;
y = z;
}
int a = 2; b = 3;
swap(a, b); // a IS THE SAME AS x inside the swap function
So, returning a reference value means that the value can be changed, for instance:
class Foo
{
public:
...
int &val() { return m_val; }
private:
int m_val;
};
Foo f;
f.val() = 4; // Will change m_val.
More information about references: C++ Faq Lite - Reference and value semantics
Now, answering your questions
const int exampleOne();
Means the object returned cannot change through the variable. It's more useful when returning objects.
int& exampleTwo();
Means the object returned is the same as the one inside the function and any change made to that object will be reflected inside the function.
const int& exampleThree();
Means the object returned is the same as the one inside the function and cannot be modified through that variable.
Never thought, that we can return a const value by reference and I don't see the value in doing so..
But, it makes sense if you try to pass a value to a function like this
void func(const int& a);
This has the advantage of telling the compiler to not make a copy of the variable a in memory (which is done when you pass an argument by value and not by reference). The const is here in order to avoid the variable a to be modified.