Persistance of object instances that are created inside methods in C++ - c++

Lets say I have a simple class that simply holds an object:
class objholder{
object ojb;
public:
setobj(object o);
}
objholder::setobj(object o){
obj = o;
}
objholder::getobj(){
return obj;
}
Lets say I create a function that creates an instance of an object which then gets passed to the objholder.
What happens to the instance of the object when the function returns? Does it persists?
What happens if I then try to access the instance of object that has been saved by the objholder will it stil contain a valid reference?
Here are some simple functions that illustrate the functionality I've described above.
void foo(objholder oh){
object temp;
oh.setobj(temp);
}
void bar(objholder oh){
object temp = oh.getobj();
}
int main(int argc, char **argv){
objholder o;
foo(o);
bar(o);
}

C++ is a language value semantics, which means that by default types are treated as values, copied, etc. unlike Java or C# that have reference semantics. Lets analyze the program:
void foo( objholder );
int main(int argc, char **argv){
objholder o; // [1]
foo(o); // [2]
bar(o); // [3]
}
void foo( objholder oh ) { // [4]
object tmp; // [5]
oh.setobject( tmp ); // [6]
} // [7]
In [1] a new object o is created in the scope of main. That object contains a subobject obj of type object initialized as per objholder default constructor. In [2] a copy of that object is done and passed to foo ([4]) that creates a local object ([5]) that is passed to the setobject member method of oh in [6], (remember: oh is a copy of the objholder in main), because objholder::setobject takes the element by value, a copy of tmp is created, and that copy is passed to oh.setobject, that in turn makes a copy and stores it in the member attribute (not shown in the code). In [7] the execution of foo completes and all local variables are destroyed in reverse order of creation, which means that tmp is destroyed, and then oh (which in turn means that the internal copy of tmp is destroyed).
At this point we are back in main where our local object o has remained untouched --all that has been processed was the copy passed to foo. Then as in the call to foo a copy is created and passed to bar.
I started noting that this is due to the value semantics in C++, compared with reference semantics in other languages as Java or C#. If the program was (syntax aside) Java, in [2] and [3] a copy of the reference would be passed, and the referred object both in main, foo and bar would be the same. This can be achieved in C++ by using pointers and references. C++ references are not just like Java/C# references, so if you come from any of those languages take time to understand the similarities and differences.

What happens to the instance of the object when the function returns? Does it persists?
It's destroyed along with the holder. But note that your objectholder copies the object passed to its setobj.
What happens if I then try to access the instance of object that has been saved by the objholder will it stil contain a valid reference?
Do you mean...
object obj;
{
objectholder holder;
holder.setobj(obj);
}
// do something to obj
? Nothing special happens (except if object does something special in its copy constructor).

The way you have done your objholder you are not "holding" the object, merely holding a copy of the object.
this just makes a copy of 'o' and stores it in 'obj'
objholder::setobj(object o)
{
obj = o;
}
if you want to keep a reference to the object you need to either pass a reference or a pointer to the object
object& obj;
objholder::setobj(object& o)
{
obj = o;
}
however by keeping a reference to object you are still not owner of the object (if i understood correctly is what you are getting at), instead you would need to use unique_ptr to take ownership of the object. By using unique_ptr you can sort of pass an object around.
that said, in order to understand life of object you should look into scopes and the free store/stack.

Related

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.

What is the point of using references to variables instead of using the actual variable? [duplicate]

I would like to clarify the differences between by value and by reference.
I drew a picture:
So, for passing by value, a copy of an identical object is created with a different reference, and the local variable is assigned the new reference, so to point to the new copy
How should I understand the following?
If the function modifies that value, the modifications appear also
within the scope of the calling function for both passing by value and by reference
I think much confusion is generated by not communicating what is meant by passed by reference. When some people say pass by reference they usually mean not the argument itself, but rather the object being referenced. Some other say that pass by reference means that the object can't be changed in the callee. Example:
struct Object {
int i;
};
void sample(Object* o) { // 1
o->i++;
}
void sample(Object const& o) { // 2
// nothing useful here :)
}
void sample(Object & o) { // 3
o.i++;
}
void sample1(Object o) { // 4
o.i++;
}
int main() {
Object obj = { 10 };
Object const obj_c = { 10 };
sample(&obj); // calls 1
sample(obj) // calls 3
sample(obj_c); // calls 2
sample1(obj); // calls 4
}
Some people would claim that 1 and 3 are pass by reference, while 2 would be pass by value. Another group of people say all but the last is pass by reference, because the object itself is not copied.
I would like to draw a definition of that here what i claim to be pass by reference. A general overview over it can be found here: Difference between pass by reference and pass by value. The first and last are pass by value, and the middle two are pass by reference:
sample(&obj);
// yields a `Object*`. Passes a *pointer* to the object by value.
// The caller can change the pointer (the parameter), but that
// won't change the temporary pointer created on the call side (the argument).
sample(obj)
// passes the object by *reference*. It denotes the object itself. The callee
// has got a reference parameter.
sample(obj_c);
// also passes *by reference*. the reference parameter references the
// same object like the argument expression.
sample1(obj);
// pass by value. The parameter object denotes a different object than the
// one passed in.
I vote for the following definition:
An argument (1.3.1) is passed by reference if and only if the corresponding parameter of the function that's called has reference type and the reference parameter binds directly to the argument expression (8.5.3/4). In all other cases, we have to do with pass by value.
That means that the following is pass by value:
void f1(Object const& o);
f1(Object()); // 1
void f2(int const& i);
f2(42); // 2
void f3(Object o);
f3(Object()); // 3
Object o1; f3(o1); // 4
void f4(Object *o);
Object o1; f4(&o1); // 5
1 is pass by value, because it's not directly bound. The implementation may copy the temporary and then bind that temporary to the reference. 2 is pass by value, because the implementation initializes a temporary of the literal and then binds to the reference. 3 is pass by value, because the parameter has not reference type. 4 is pass by value for the same reason. 5 is pass by value because the parameter has not got reference type. The following cases are pass by reference (by the rules of 8.5.3/4 and others):
void f1(Object *& op);
Object a; Object *op1 = &a; f1(op1); // 1
void f2(Object const& op);
Object b; f2(b); // 2
struct A { };
struct B { operator A&() { static A a; return a; } };
void f3(A &);
B b; f3(b); // passes the static a by reference
When passing by value:
void func(Object o);
and then calling
func(a);
you will construct an Object on the stack, and within the implementation of func it will be referenced by o. This might still be a shallow copy (the internals of a and o might point to the same data), so a might be changed. However if o is a deep copy of a, then a will not change.
When passing by reference:
void func2(Object& o);
and then calling
func2(a);
you will only be giving a new way to reference a. "a" and "o" are two names for the same object. Changing o inside func2 will make those changes visible to the caller, who knows the object by the name "a".
I'm not sure if I understand your question correctly. It is a bit unclear. However, what might be confusing you is the following:
When passing by reference, a reference to the same object is passed to the function being called. Any changes to the object will be reflected in the original object and hence the caller will see it.
When passing by value, the copy constructor will be called. The default copy constructor will only do a shallow copy, hence, if the called function modifies an integer in the object, this will not be seen by the calling function, but if the function changes a data structure pointed to by a pointer within the object, then this will be seen by the caller due to the shallow copy.
I might have mis-understood your question, but I thought I would give it a stab anyway.
As I parse it, those words are wrong. It should read "If the function modifies that value, the modifications appear also within the scope of the calling function when passing by reference, but not when passing by value."
My understanding of the words "If the function modifies that value, the modifications appear also within the scope of the calling function for both passing by value and by reference" is that they are an error.
Modifications made in a called function are not in scope of the calling function when passing by value.
Either you have mistyped the quoted words or they have been extracted out of whatever context made what appears to be wrong, right.
Could you please ensure you have correctly quoted your source and if there are no errors there give more of the text surrounding that statement in the source material.

Is there anything incorrect about "return std::move(*this);"?

I know that a certain object is only ever created as a temporary object (it's a private member object within a library). Sometimes, that object is further initialized by chaining member functions together (TempObj().Init("param").Init("other param")). I would like to enable move construction for another object using that temporary instance, and so I was wondering if there was anything incorrect about return std::move(*this).
struct TempObj
{
TempObj &&Member() { /* do stuff */ return std::move(*this); }
};
struct Foo
{
Foo(TempObj &&obj);
};
// typical usage:
Foo foo(TempObj().Member());
Is it functionally equivalent to this?
struct TempObj
{
TempObj(TempObj &&other);
TempObj Member() { /* do stuff */ return *this; }
};
Foo foo(TempObj().Member());
With move semantics, you don't want (or need) to return r-value references from functions ... r-value references are there to "capture" unnamed values or memory addresses. When you return a r-value reference to an object that is in-fact an l-value from the standpoint of the caller, the semantics are all wrong, and you create the opportunity for needless surprises to arise when others are using your object's methods.
In other words, it would be better to orient your code to look like this:
Foo foo(std::move(TempObj().Member()));
and have TempObj::Member simply return a l-value reference. This makes the move explicit, and there are no suprises involved for someone using your object's methods.
Finally, no, it's not functionally or semantically equivalent to your last example. There you are actually making a temporary copy of the object, and that copy will be an r-value object (i.e., an unamed object in this scenario) ... since the assumption with r-value references is that the object is either an unamed value or object, and it can therefore be harmlessly modified by a function you pass it to that takes an r-value reference argument. On the other-hand, if you've passed a copy of an object to a function, then the function cannot modify the original. It will simply modify the referenced temporary r-value, and when the function exits, the temporary r-value copy of the object will be destroyed.

C++ class instantiation theory

#include <iostream>
using namespace std;
class A {
public:
A() {
cout << "Default Ctor" << endl;
}
};
int main() {
A(); // <------- Problem
return 0;
}
It shows Default Ctor on console. My questions
Is is valid?
If so, how did it instantiate since I didn't use new or any object?
You are creating a new object with A().
Is is valid?
Yes it is.
If so, how did it instantiate since I didn't use new or any object?
new simply creates the object in dynamic memory. You're creating the object in automatic memory. Also, just because you didn't give the object a name, doesn't mean it isn't created.
Think of this:
int foo() { return 1; }
int main()
{
foo();
}
Leaving optimizations aside Did foo() actually return 1? Yes it did. Just that you're not using it.
EDIT:
Let's break it down a bit:
A(); //creates a temporary unnamed object in automatic storage
A a; //creates an object a of type A in automatic storage
A a(); //creates no object, but declare a function a returning A and taking no parameters
A a(A()); //these two are equivalent
A a = A(); //creates a temporary unnamed object and creates an object a in automatic storage
//using the compiler-generated copy constructor
A a;
a = A(); //creates an object a in automatic storage
//creates an unnamed temporary object and uses the compiler-generated assignment operator
//to assign it to a
A a = &A(); //invalid, &A() is the address of a temporary a, which is illegal
Is is valid?
Yes, It is valid
What exactly happens?
A();
Creates a temporary nameless object of the type A by calling its default no argument constructor but the object is destructed by the time the next statement is executed since.
If so, how did it instantiate since I didn't use new or any object?
You can create objects on the local/automatic storage or on dynamic storage depending on your usage.
When you use new objects are created on dynamic storage(heap), when you create a object as you have it is created on the local/automatic storage(stack).
So using new only determines where the object will be created not whether it will be created.
What are Temporary Nameless objects?
You do not always need to name an object to instantiate them.
For Ex:
While calling function, when you pass objects by value temporary nameless objects are created and automatically destroyed all the time.These are objects which do not have any name and hence cannot be explicitly referred through program but they do serve the purpose for which they were created.
In simple words,
You are creating a nameless temporary object on the local/automatic storage which does not exist once the statement completes execution.

Pass by reference and value in C++

I would like to clarify the differences between by value and by reference.
I drew a picture:
So, for passing by value, a copy of an identical object is created with a different reference, and the local variable is assigned the new reference, so to point to the new copy
How should I understand the following?
If the function modifies that value, the modifications appear also
within the scope of the calling function for both passing by value and by reference
I think much confusion is generated by not communicating what is meant by passed by reference. When some people say pass by reference they usually mean not the argument itself, but rather the object being referenced. Some other say that pass by reference means that the object can't be changed in the callee. Example:
struct Object {
int i;
};
void sample(Object* o) { // 1
o->i++;
}
void sample(Object const& o) { // 2
// nothing useful here :)
}
void sample(Object & o) { // 3
o.i++;
}
void sample1(Object o) { // 4
o.i++;
}
int main() {
Object obj = { 10 };
Object const obj_c = { 10 };
sample(&obj); // calls 1
sample(obj) // calls 3
sample(obj_c); // calls 2
sample1(obj); // calls 4
}
Some people would claim that 1 and 3 are pass by reference, while 2 would be pass by value. Another group of people say all but the last is pass by reference, because the object itself is not copied.
I would like to draw a definition of that here what i claim to be pass by reference. A general overview over it can be found here: Difference between pass by reference and pass by value. The first and last are pass by value, and the middle two are pass by reference:
sample(&obj);
// yields a `Object*`. Passes a *pointer* to the object by value.
// The caller can change the pointer (the parameter), but that
// won't change the temporary pointer created on the call side (the argument).
sample(obj)
// passes the object by *reference*. It denotes the object itself. The callee
// has got a reference parameter.
sample(obj_c);
// also passes *by reference*. the reference parameter references the
// same object like the argument expression.
sample1(obj);
// pass by value. The parameter object denotes a different object than the
// one passed in.
I vote for the following definition:
An argument (1.3.1) is passed by reference if and only if the corresponding parameter of the function that's called has reference type and the reference parameter binds directly to the argument expression (8.5.3/4). In all other cases, we have to do with pass by value.
That means that the following is pass by value:
void f1(Object const& o);
f1(Object()); // 1
void f2(int const& i);
f2(42); // 2
void f3(Object o);
f3(Object()); // 3
Object o1; f3(o1); // 4
void f4(Object *o);
Object o1; f4(&o1); // 5
1 is pass by value, because it's not directly bound. The implementation may copy the temporary and then bind that temporary to the reference. 2 is pass by value, because the implementation initializes a temporary of the literal and then binds to the reference. 3 is pass by value, because the parameter has not reference type. 4 is pass by value for the same reason. 5 is pass by value because the parameter has not got reference type. The following cases are pass by reference (by the rules of 8.5.3/4 and others):
void f1(Object *& op);
Object a; Object *op1 = &a; f1(op1); // 1
void f2(Object const& op);
Object b; f2(b); // 2
struct A { };
struct B { operator A&() { static A a; return a; } };
void f3(A &);
B b; f3(b); // passes the static a by reference
When passing by value:
void func(Object o);
and then calling
func(a);
you will construct an Object on the stack, and within the implementation of func it will be referenced by o. This might still be a shallow copy (the internals of a and o might point to the same data), so a might be changed. However if o is a deep copy of a, then a will not change.
When passing by reference:
void func2(Object& o);
and then calling
func2(a);
you will only be giving a new way to reference a. "a" and "o" are two names for the same object. Changing o inside func2 will make those changes visible to the caller, who knows the object by the name "a".
I'm not sure if I understand your question correctly. It is a bit unclear. However, what might be confusing you is the following:
When passing by reference, a reference to the same object is passed to the function being called. Any changes to the object will be reflected in the original object and hence the caller will see it.
When passing by value, the copy constructor will be called. The default copy constructor will only do a shallow copy, hence, if the called function modifies an integer in the object, this will not be seen by the calling function, but if the function changes a data structure pointed to by a pointer within the object, then this will be seen by the caller due to the shallow copy.
I might have mis-understood your question, but I thought I would give it a stab anyway.
As I parse it, those words are wrong. It should read "If the function modifies that value, the modifications appear also within the scope of the calling function when passing by reference, but not when passing by value."
My understanding of the words "If the function modifies that value, the modifications appear also within the scope of the calling function for both passing by value and by reference" is that they are an error.
Modifications made in a called function are not in scope of the calling function when passing by value.
Either you have mistyped the quoted words or they have been extracted out of whatever context made what appears to be wrong, right.
Could you please ensure you have correctly quoted your source and if there are no errors there give more of the text surrounding that statement in the source material.