Obtaining object from function by reference instead by value - c++

I wonder if code below is correct - it works in this case but it may be just because of its simplicity. What makes me wonder: function (f1) returns object by value but in function which called it (f2) I obtain this object by reference not by value. Is this a problem? I wonder because it looks a bit weird to me but it works and i think it should works. Because object is created on the stack of f1 and then returned (by value) to stack f2 and after that a reference is obtained to this object on f2 stack which was created on f1 stack. What do you think about this?
class A {
public:
A(){a=100; b=200;}
int a;
int b;
};
typedef boost::shared_ptr<A> AP;
AP get(){
AP a = AP(new A());
return a;
}
AP get2(){
AP const& a = get();
return a;
}
int main() {
AP const& a = get2();
std::cerr << a->a << std::endl;
return 0;
}

It's weird, but safe.
Binding a temporary object to a reference extends its lifetime to that of the reference; so what you're doing is equivalent to creating a local object variable. The use of a reference adds obfuscation, requiring the reader to know these odd rules to understand what's happening, but doesn't change the program's validity or behaviour.

In the both cases
AP const& a = get();
and
AP const& a = get2();
You bind a temporary object with a const reference. The object will be alive while there will be alive the reference. So there is no problem with your code.

Related

How to return member that can be changed?

Multi thread enviroment . The content of Foo can be multi thread.
class Foo
{
public:
const A & getA() {return a_;} //has guard
void setA(A newA){a_ = newA;} //has guard
private:
A a_;
};
caller:
A a = foo.getA();
in another question that i asked someone told me that
If you return const& it's guaranteed that life time of variable will be prolonged to lifetime of the reference
, so according to this i dont need to copy the value and i safe even if call to setA on foo done right after i call to getA, but a lot of argument against it was araised , so i feel that this is not correct.
I want to be on the safe side so i change the signature to be :
A & getA() {return a_;}
but the compiler still give me warning that i have reference to local variable. i dont understand why, because as far as i understand (new to cpp) the return value is a copy of foo.a, so what the problem with this?
i am not worried about change of a_ content.(_a.age =4) . i worry about call to set and that my 'a' in the caller will be illegal
You need to be more careful who you listen to. The only time the lifetime of something gets extended if a temporary object is bound immediately to a const-reference. For example, like so:
Foo bar() { return Foo(); }
int main()
{
Foo const & f = bar();
/* stuff */
} // the object referred to by f is extended till here
Your situation is nothing like that. In particular, returning a const-reference does not create a temporary object, so there's nothing here who's life gets prolonged. In particular, the following is definitely an error:
A const & bar() { Foo x; return x.getA(); }
int main()
{
A const & a = bar(); // dangling reference; object dies upon return from Foo::getA()
}

Get shared_ptr by reference with dynamic_pointer_cast

Is it ok to get the return value from dynamic_pointer_cast by reference, or can it cause problem?
struct A
{
};
struct B : public A
{
};
int main()
{
shared_ptr<A> b = make_shared<B>();
auto &a = dynamic_pointer_cast<A>(b);
//auto a = dynamic_pointer_cast<A>(b);
return 0;
}
Even if it were possible, it wouldn’t do what you want:
[The aim is that] the reference counter is not increased
It would still be increased since dynamic_pointer_cast returns a new shared_ptr copy anyway.
Your code doesn’t work since the reference would then be bound to the temporary object returned by the dyanamic_pointer_cast and this is forbidden.
Using a const reference would work (since const& is allowed to bind to a temporary) but the result would still be the same: the cast would create a new instance of a shared_ptr, and increment the reference count.

passing a pointer of a reference/passing a reference of a reference

Do I get a usual pointer as I pass a pointer to a reference of a variable or do i get a pointer to the reference? And what do i get as I pass a reference to a reference?
I am using the stack implementation of the standard library in a class, and i want to have some wrapper methods to prevent illegal access of the stack, but i am getting strange segfaults which i narrowed down to my getter-methods considering the stack.
Should those methods give back a clean reference/pointer to the original variable stored in the stack?
int& zwei() { return stack.top() };
and
int* eins() { return &stack.top() };
There is no such thing as a "pointer to a reference". References are aliases, and so taking the address of any of them will give a pointer to the same object:
int a;
int & b = a;
assert(&a == &b);
Your functions both return a valid result provided that the stack object is still alive in the scope of the function return.
std::stack<int> s;
int & foo() { return s.top(); } // OK, maybe
int * goo() { return &s.top(); } // ditto
int & boo() { std::stack<int> b; return b.top(); } // No! Dangling reference!
You should also check that the stack isn't empty, in which case top() is not valid.
(I should also council against calling a variable by the same name as a type, even though the type's name is std::stack.)

Using a const reference to a returned by value value

Look at the following example:
string foo(int i) {
string a;
... Process i to build a ...
return a;
}
void bar(int j) {
const string& b = foo(j);
cout << b;
}
I know RVO and NRVO, but I thought that in order to do that, I need to write bar as the following:
void bar(int j) {
string b = foo(j);
cout << b;
}
Both versions seem to work, and I believe with the same performance.
Is it safe to use the first version (with the const reference)?
Thanks.
Assigning a temporary to a const reference is perfectly valid. The temporary object will live until the reference goes out of scope.
While it does not make sense in your example, this feature is often used for function arguments:
string foo(int i) {
string a;
// ...
return a;
}
void bar(const string& str) {
// ...
}
void buzz() {
// We can safely call bar() with the temporary string returned by foo():
bar(foo(42));
}
It's safe in this simple case. It's easy to add code which makes it unsafe, however, and it's confusing to anyone who knows C++: why do you need a reference here? There's no reason to do so, and such code should generally be avoided.
A const-reference is allowed to bind to a temporary, and the live-time of the temporary will be extended to the live-time of the const-reference. So yes, it is safe to use.
Is it safe to use the first version (with the const reference)?
Yes. Binding a temporary to a const reference lengthens the lifetime of the temporary to the lifetime of the reference itself, which is the scope in which the reference is declared:
void f()
{
const string& a = foo(10);
//some work with a
{
const string& b = foo(20);
//some work with b
} //<----- b gets destroyed here, so the temporary also gets destroyed!
//some more work with a
} //<----- a gets destroyed here, so the temporary associated
//with it also gets destroyed!
Herb Sutter has explained this in great detail in his article:
A Candidate For the “Most Important const”
It is worth reading. Must read it.

function returning this pointer in c++

1st code:
#include <iostream>
using namespace std;
class demo
{
int a;
public:
demo():a(9){}
demo& fun()//return type isdemo&
{
return *this;
}
};
int main()
{
demo obj;
obj.fun();
return 0;
}
2nd code:
#include <iostream>
using namespace std;
class demo
{
int a;
public:
demo():a(9){}
demo fun()//return type is demo
{
return *this;
}
};
int main()
{
demo obj;
obj.fun();
return 0;
}
what is the difference between these two codes as both are working in gcc?i am new here so forgive me if my way of asking is wrong.
demo & fun() returns a reference to the current object. demo fun() returns a new object, made by copying the current object.
Both are valid but are different. In the first case demo& fun() a reference to the same object is returned, in the second case a new object is created. While both are the same, the semantics differ, run this example:
#include <iostream>
struct test {
int x;
test() : x() {}
test& foo() { return *this; }
test bar() { return *this; }
void set( int value ) { x = value; }
};
int main() {
test t;
t.foo().set( 10 ); // modifies t
t.bar().set( 5 ); // modifies a copy of t
std::cout << t.x << std::endl; // prints 10
}
Apart from what #Erik said about the return type, a little excursus on the this-pointer:
The following is equivalent:
struct my_struct{
my_struct* get_this() const { return this; }
};
my_struct obj;
my_struct* obj_this = ob.get_this();
std::cout << std::boolalpha; // to display true/false instead of 1/0
std::cout << "&obj == obj_this = " << &obj == obj_this << "\n";
The this pointer is just the pointer to that object, you can think of it as a hidden parameter. It's more understandable in the C way:
typedef struct my_struct{
int data;
// little fidgeting to simulate member functions in c
typedef void (*my_struct_funcptr)(struct my_struct*,int);
my_struct_funcptr func;
}my_struct;
// C++ does something similar to pass the this-pointer of the object
void my_struct_func(my_struct* this, int n){
this->data += n;
}
my_struct obj;
obj.data = 55;
// see comment in struct
obj.func = &my_struct_func;
obj.func(&obj, 15);
// ^^^^ - the compiler automatically does this for you in C++
std::cout << obj.data; // displays 70
Consider your function.
demo fun(){return *this;}
Here you are returning by value so one temporary object will be created which will be destroyed, once you assign the return value of fun to some other object.
While in case when you pass the reference, no object will be created newly, but it will pass actual object and even after assigning function return value object will not destroy till main object(used inside fun, in ur case its the object calling the function) won't go out of scope.
The concept you are trying to understand can be explained in more detail with other example.
consider function that is taking object as argument and returning object as argument.(also consider we have object that contains a pointer, we will assign value to pointer by first allocating memory to pointer and a destructor, which will free memory hold by pointer of object). Now when you return object as pass by value, temporary object will be created, that will have exact copy of main object(and temporary object's pointer will also point to same address or you can say holds the same address). Now inside main(), you assign/initialize any object with return value(object) of function. But when your temp object will be destroyed after assigning value, it will also free the memory because of destructor and when you try to fetch the same address value through assigned object(inside main() ) you will get error as that memory has been already freed.
But if you would have return value using reference, object returned by object won't destroy as main obj(inside function or through which we have called the function) is in scope and your pointer won't loose its memory. Making possible for assigned object to fetch address value through its pointer and avoid undesirable result.
In code 1 demo obj creates a fresh copy of demo. obj is initialised using demo's default constructor 'demo():a(9){}'. obj.fun() returns a reference to (already existing) obj.
In code 2 obj.fun() creates a new demo type object using demo's copy constructor (in your case it is compiler generated) and returns that copy to the caller.
Both code are valid.
1st code fun() is returning a reference to current object
2nd code fun() is returning the copy (by value) of the object
For 1st case, If you decide to return by value
then prefer to return a const
reference; i.e. const demo& fun();
and later you can copy it if needed.
Simply returning reference makes the
object modifiable, which may
accidently edit the content without
intent
For 2nd case, Do NOT return the object by value,
because it can create unnecessary
temporary copy which will effect
the memory/performance of your code