Scope of variable local to static method in C++ - c++

I was trying to create an instance of an object with private constructor. Is this method correct?
#include <iostream>
using namespace std;
class A{
int y;
A(int y=2):y(y){};
public:
A(const A &obj){
cout<<"copy Cotr is called"<<endl;
this->y=obj.y;
}
int* addr(){
int *a=&y;
return a;
}
static A create(int y1=2){
class A a(y1);
cout<<&a<<endl;
return a;
}
void print(){
cout<<y<<endl;
}
};
int main(){
A o1=A::create(1);
A o2=A::create(3);
cout<<&o1<<" "<<&o2<<endl;
return 0;
}
The output is:
0x7ffd20d2f280
0x7ffd20d2f284
0x7ffd20d2f280 0x7ffd20d2f284
In the above code, I fail to understand few points:
create() returns a value, so during assignment which take place in A o1=A::create(1);, copy constructor should be called but it isn't. why?
Is this some undefined behavior as the address of the object created in create() and in main() are same and the object in create() is local and goes out of scope after the function ends.

create() returns a value, so during assignment which take place in A o1=A::create(1);, copy constructor should be called but it isn't. why?
You have copy-elision (Demo) which is an optimization allowed by standard.
The object is directly constructed in final place and no copy/move is done.
Some copy-elisions is even mandatory in C++17. (half of them in your case).
Is this some undefined behavior as the address of the object created in create() and in main() are same and the object in create() is local and goes out of scope after the function ends.
With copy elision, as object is directly constructed in final place, there is indeed only one address, it is as-if the local variable of create was the one from main.

This:
A a = x();
is different than this:
A a;
a = x();
In the second case you have a copy, in the first you don't.
To answer your second question, the object created in create() is local all right, but then it's copied back to the caller (actually, moved). Since the stack frame is the same, the local address is the same. But when it's copied, you have two different objects.

Thanks for all the answers. Dug deep into it and now answering my own question.
For the learned:
This is major instance of copy elision in C++ 17.
Answer ends for you. For the one who still didn't understood:
This method has no errors and do not show any undefined behavior. Most of the compilers uses C++11 or C++17 these days which is well integrated with copy elision(copy omission).
create() returns a value, so during assignment which take place in A
o1=A::create(1);, copy constructor should be called but it isn't. why?
Copy constructor is not called as the return type is prvalue(pure rvalue) and the compiler optimizes the program in such a way that the return value is created directly into the storage where the function's return value would otherwise be copied or moved to. So, actually no move or copy takes place so no move/copy constructor is called. Even after the end of create() destructor too is not called.
Is this some undefined behavior as the address of the object created
in create() and in main() are same and the object in create() is local
and goes out of scope after the function ends.
So, even after the function create() ends, the object dont get pushed out of scope or the destructor for that object is not called. As the object is created in not in the create() but in the main() itself. It is not an undefined behavior but a major benefit of C++ as unnecessary pointers and functions need not to be declared or invoked. Here, NRVO takes place.
In a return statement, when the operand is the name of a
non-volatile object with automatic storage duration, which isn't a
function parameter or a catch clause parameter, and which is of the
same class type (ignoring cv-qualification) as the function return
type. This variant of copy elision is known as NRVO, "named return
value optimization".

Related

Using variables by reference

We have Myclass &funcref(); and Myclass func(); and assign the return value to a variable (not a variable reference). If I understand correctly we use the copy constructor in both cases. The only difference is that funcref() returns a reference, and we copy over what is refers to into our object, while in func(), we copy the object while returning.
If we assign it to a variable reference, only func() still needs a copy constructor.
I hope everything until now is correct - if not, please point out my missunderstanding.
Now my question:
It seems like whether we assign the return value of func() to a variable, or a variable reference, it does not change anything at all? Is there any case in which those two will differ? At least when they are assigned, it seems like the process is the same, but I may be wrong.
In code:
class My_class {
//Anything may be here
};
My_class func();
My_class &funcref();
int main() {
My_class a = func(); //Copy operator used?
const My_class &b = func(); //Why does this need to be constant? Also, this uses copy operator, right?
My_class c = funcref(); //Copy operator used?
My_class &d = funcref(); //Here, we do not need a copy operator, right?
}
Main question: Except for b being const, is there any difference between a and b? Both seem to be on the stack of main, so do they differ in any way?
If I understand correctly we use the copy constructor in both cases.
Not quite. In C++11, move constructor will be used in case of Myclass func() (and compiler is allowed to optimise the copy / move away).
Since C++17, there is neither move nor copy in case of Myclass func().
Is there any case in which those two will differ?
It is somewhat unclear what cases you are asking about. There is a differenceiIn the case where the function returns a reference.
if I am calling any function that returns a non-reference, should I assign the output as a reference, or not as a reference?
Typically, you should use an object variable because that is simpler and doesn't involve the cognitive load of having to understand reference bound temporary lifetime extension rules.
Only case I can think of where reference variable for prvalue makes sense is a template context where the called function might return a reference, or a non-reference object that acts as a reference wrapper. I believe that case is the reason why temporary lifetime extension exists.

Returning member unique_ptr from class method

I am trying to return a std::unique_ptr class member (trying to move the ownership) to the caller. The following is a sample code snippet:
class A {
public:
A() : p {new int{10}} {}
static std::unique_ptr<int> Foo(A &a) {
return a.p; // ERROR: Copy constructor getting invoked
// return std::move(a.p); WORKS FINE
}
std::unique_ptr<int> p;
};
I thought the compiler (gcc-5.2.1) would be able to do return value optimization (copy elision) in this case without requiring the explicit intent via std::move(). But that isn't the case. Why not?
The following code seems to be working fine, which seems equivalent:
std::unique_ptr<int> foo() {
std::unique_ptr<int> p {new int{10}};
return p;
}
The rule in [class.copy] is:
[...] when the expression in a return statement is a (possibly
parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to
select the constructor for the copy is first performed as if the object were designated by an rvalue.
In this example:
std::unique_ptr<int> foo() {
std::unique_ptr<int> p {new int{10}};
return p;
}
p is the name of an object with automatic storage duration declared in the body of the function. So rather than copying it into the return value, we first try to move it. That works fine.
But in this example:
static std::unique_ptr<int> Foo(A &a) {
return a.p;
}
that doesn't apply. a.p isn't the name of an object at all, so we don't try overload resolution as if it were an rvalue, we instead just do the normal thing: try to copy it. This fails, so you have to explicitly move() it.
That's the wording of the rule, but it might not answer your question. Why is this the rule? Basically - we're trying to be safe. If we're naming a local variable, it's always safe to move from it in a return statement. It will never be accessed again. Easy optimization, no possible downside. But in your original example, a isn't owned by this function, neither is a.p. It's not inherently safe to move from it, so the language won't try to do it automatically.
Copy elision can't apply (among other reasons) since a.p is a std::unique_ptr, which is uncopyable. And since a.p has a lifetime beyond the body of A::Foo(A&), it would be very surprising (as in, surprising to the person writing the code) if the compiler automatically tried to move from a.p, which would likely wreck the class invariants of a. It would work if you return std::move(a.p);, but that explicitly steals a.p.

Why is the copy constructor called when we return an object from a method by value

why copy constructor is called when we return an object from a method by value. please see my below code in that i am returning an object from a method while returning control is hitting the copy constructor and then returning. i am not understood following things:
1) why it is calling copy constructor.
2)which object is passing implicitly to copy constructor,
3)to which object copy constructor will copy the content,
4)what is the necessity of copying the object content while returning. so plz help.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class ClassA
{
int a, b;
public:
ClassA()
{
a = 10;
b = 20;
}
ClassA(ClassA &obj)
{
cout << "copy constructor called" << endl;
}
};
ClassA function (ClassA &str)
{
return str;
}
int main ()
{
ClassA str;
function(str);
//function(str);
return 0;
}
I'll try to answer all the questions at once.
The behavior you are observing is due to the way returning an object by value works in C++. First, a temporary object is copy-constructed (or move-constructed, in C++11) from the value returned by your function. Then, if this return value is used to initialize another object, such as in:
Class c = fxn();
The object c is copy-constructed (or move-constructed, in C++11), from that temporary.
This said, an implementation is allowed to elide one (in your concrete case) or both of these calls to the copy or move constructor per paragraph 12/8.31 of the C++11 Standard even though those constructors have side effects, and construct the function's return value directly in c:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class
object, even if the constructor selected for the copy/move operation and/or the destructor for the object
have side effects. In such cases, the implementation treats the source and target of the omitted copy/move
operation as simply two different ways of referring to the same object, and the destruction of that object
occurs at the later of the times when the two objects would have been destroyed without the optimization.122
This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which
may be combined to eliminate multiple copies):
— in a return statement in a function with a class return type, when the expression is the name of a
non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified
type as the function return type, the copy/move operation can be omitted by constructing
the automatic object directly into the function’s return value
— [...]
— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved
to a class object with the same cv-unqualified type, the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted copy/move
— [...]
The reason why I wrote that in your specific case only one of the calls to the copy or move constructor can be elided is the sentence in bold in the first bullet of the Standard quote above:
[...] (other than a function or catch-clause parameter) [...]
If you are returning a parameter of your function, copy elision is inhibited.
Also notice, that the signature of your constructor should be:
Class(Class const& c)
// ^^^^^
There is no reason for you to accept an lvalue reference to non-const in the copy constructor, since you are not going to modify the object you are copying from.
Even worse, the above would prevent copy construction from rvalues (like temporaries), so the following code would not compile:
Class foo() { return Class(); }
Even though an implementation is allowed to elide the copy, a viable and accessible copy constructor (or move constructor, if we're talking about a move) should still be present.
The function returns an object. Hence, that object must exist. Hence, that object must be created from somewhere. Clearly this means that one of its constructors shall be used. The question is, which one?
Since you chose to return str;, this is the instruction that shall be used to create it. How else could you use that return instruction to create and return an object and yet not use the copy constructor? It is clear that you need to use str to initialize the returned value, so you're not going to use the other option (the parameterless constructor).
The copy constructor is called because you call by value not by reference. Therefore a new object must be instantiated from your current object since all members of the object should have the same value in the returned instance. Because otherwise you would be returning the object it self, which would be returning by reference. In this case modifying the reference object would change the original as well. This is generally not a behavior one wants when returning by value.
ClassA function (ClassA &str)
{
return str;
}
object str will copy-constructored in a temporary object with type ClassA for further usage. However compiler can omit it due to optimization.

Unexpected destructor call occurs when paired with move constuctor

The following code was compiled and run in Visual Studio 2012 Express for Windows Desktop, as a learning exercise.
#include <cstdio>
class X
{
public:
X() { printf("default constructed\n"); }
~X() { printf("destructed\n");}
X(const X&) { printf("copy constructed\n"); }
X(X&&) { printf("move constructed\n"); }
X & operator= (const X &) { printf("copy assignment operator\n"); }
};
X A() {
X x;
return x;
}
int main() {
{
A();
}
std::getchar();
}
When compiled with compiler optimizations disabled (/Od), the resulting output indicates that the destructor is called twice. This is a problem given that only one object is constructed. Why is the destructor being called twice? Wouldn't this be a problem if the class was managing it own resources?
default constructed
move constructed
destructed
destructed <<< Unexpected call
I tried a couple of experiments to try and explain the output, but ultimately these didn't lead to any useful explanations.
Experiment 1: When the same code is compiled with optimizations enabled (/O1 or /O2), the resulting output is:
default constructed
destructed
which indicates that the Named Return Value Optimization has elided the call to the move constructor, and masked the underlying problem.
Experiment 2: Disabled the optimization and commented out the move constructor. The output generated was what I expected.
default constructed
copy constructed
destructed
destructed
Keep in mind that when an object is the source of a move operation it will still be destroyed. So the source of the move needs to put itself in a state such that being destructed will not release resources that it no longer owns (since they were moved to another object). For example, any raw pointers (that will now be owned by the move constructed object) in the source object should be set to NULL.
The X in A is destroyed when it goes out of scope.
A returns a temporary object (constructed from X by the move constructor) which is a separate instance. This is destroyed in the caller's scope. That will cause the destructor to be called again (on the temporary).
The move constructor was picked because the compiler detected that X was going to be destroyed immediately afterward. To use this approach, the move constructor should nullify or reset any data in the original object so that the destructor will not invalidate any data that has been taken over by the destination of the move.
When you pass an rvalue by value, or return anything by value from a function, the compiler first gets the option to elide the copy. If the copy isn’t elided, but the type in question has a move constructor, the compiler is required to use the move constructor.
http://cpp-next.com/archive/2009/09/move-it-with-rvalue-references/
When you exit from the scope in which the temporary object was created, it is destroyed. If a reference is bound to a temporary object, the temporary object is destroyed when the reference passes out of scope unless it is destroyed earlier by a break in the flow of control.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr382.htm
The RVO can produce different behavior from the non-optimized version:
Return value optimization, or simply RVO, is a compiler optimization technique that involves eliminating the temporary object created to hold a function's return value.[1] In C++, it is particularly notable for being allowed to change the observable behaviour of the resulting program.[2]
http://en.wikipedia.org/wiki/Return_value_optimization
Although Michael's and jspcal answers are accurate, they didn't answer the heart of my question, which was why were there two destructor calls made. I was expecting just one.
The answer is that function A() returns a temporary object. Always. This is how function return values work, and move-semantics has no bearing on this fact. I guess Michael and jspcal assumed that I had not missed such a basic fact. I equated the term "moved" with the concept of "swap". When swapped, objects are not constructed and destructed. Hence I was expecting just one destructor call.
Since the returned object must be constructed and destructed, the second destructor call was made (and a second constructor call).
Now, the actual constructor selected to be executed depends on what is provided in the class definition. If a move-constructor is available, that will be called. Otherwise the copy constructor will be called.

C++: Return by reference to return by value

I've been reading Myers book and came across the item on returning by reference/pointer vs by value.
The point is, if our function for example is like this:
ClassA& AddSomething(ClassA classA)
{
ClassA tempClassA;
//... do something on tempClassA
return tempClassA;
}
This would not work because we are returning a reference to a object that was created on the stack and it is dead now that the function is done.
He gives two solutions:
Using a local static ClassA inside the function. This has its
problems but atleast we can be sure that object exists.
Return as an object:
ClassA AddSomething(ClassA classA)
{
ClassA tempClassA;
//... do something on tempClassA
return tempClassA;
}
Now if I'm to do:
ClassA obj1;
ClassA obj2 = AddSomething(obj1);
My confusion now is, when executing this line:
A 'copy' of tempClassA is made and passed to the copy constructor
of ClassA (to initialize obj2)? OR
tempClassA is passed itself to the copy constructor of ClassA,
because copy constructor takes a reference.
So basically, whats passed to the copy constructor is a reference to tempClassA (which was created in stack inside the function) or a reference to a copy of tempClassA.
Also, another question I have is, I have read that if I get a reference of a function local variable, in that case the local variable will not be deleted.
For example,
ClassA & classRef = AddSomething(obj1);
In this case, if AddSomething() is returning a reference, then classRef not be pointing to a deleted reference because the local variable will be retained. Have I understood this correctly?
At worst, you're right: a copy of tempClassA is passed to the copy constructor. But compilers are allowed to eliminate that copy and construct the result in place form tempClassA. This is known as the "Return Value Optimization", or RVO. I don't know of a compiler that doesn't do this.
When an object is returned by value, there are two copies taking place: one from the local variable into the return value, and one from the return value into the target object. However, the implementation is allowed to elide one or both of these copies; this is called return value optimisation (RVO) in the first case, and copy elision in the second.
Object some_function() {
return Object(); // copy Object() into return value; candidate for RVO
}
Object another_function() {
Object obj;
return obj; // copy obj into return value; candidate for NRVO
}
Object result = some_function(); // copy return value into result; candidate for copy elision
The second function above is a candidate for a refinement type of RVO called named return value optimisation; the simplest form of RVO applies only to return statements that construct the return value inplace.
Regarding your second question, lifetime extension only applies to const references to objects returned by value; your code in the second question will not extend the lifetime of any object. See Returning temporary object and binding to const reference for more details.
You can never return a function local variable by reference. It would NOT work even if you used const reference to capture the returned value like this:
const ClassA& classRef = AddSomething(obj1);
Because if AddSomething returns a local object by reference, it'll be a dangling reference to a non-existing object by the time classRef gets to reference it.