Example class:
class myclass
{
int a;
int b;
public:
myclass() {}
myclass(int x, int y)
{
a = x;
b = y;
}
};
Function:
myclass function()
{
return myclass(2, 3);
}
This line I do not understand:
return myclass(2, 3);
How is it possible to return object like this?
Looks like copy constructor is being used but constructors shouldn't return any value? (c++ beginner language please)
The return statement has a specific syntax: return expression where expression is convertible to the function return type.
So myclass(2, 3) is convertible to the return type (it is the same type). You could also have used return {2,3};.
From the link we also note:
Returning by value may involve construction and copy/move of a
temporary object, unless copy elision is used.
The statement
return myclass(2, 3);
does two things:
First a temporary object is created. This is what myclass(2, 3) does. It creates an object, calling the appropriate constructor.
The temporary object is returned, by value which means it's copied (or more likely the copy is elided as part of return value optimizations).
myclass(2, 3) is an expression that evaluates to a new (temporary) object of type myclass, constructed by invoking the myclass::myclass(int, int) constructor.
return myclass(2, 3); uses the value of such expression (the newly constructed myclass) as return value of function function. This in turn possibly invokes a copy constructor to copy the value from the temporary location where it has been constructed to whatever location is used for the return value (unless RVO kicks in, which should be mandatory in some recent C++ standard).
Related
Here is a fragment of a program:
cls fun(cls a)
{
cls v;
v = a.scale(2.0);
return v;
}
int main()
{
cls a(0.0,1.0,2.0);
cls a2;
a2 = fun(a);
return 0;
}
In the above code assume that the class definition of the class "cls" has the constructor function and the "scale" function already defined. My doubt is in the main function we have instantiated the object a2 and after that we are assigning it to the return value of the function. So, why will the copy constructor get called in this case? (I am following some resource to understand the OOP using C++ and it is mentioned over there that in the above case the copy constructor gets called.)
Also, in the above code if I write:
cls a2 = fun(a);
Then, from my understanding, the copy constructor must be called (because we are instantiating a2 as a copy of something). Now, the fun(a) returns a temporary object, but the parameter of the copy constructor function takes a reference value since we cannot take the reference value of a temporary object, shouldn't this give an error?
The compiler generated copy constructor takes a const reference as the parameter.
An anonymous temporary is allowed to bind to a const reference, so compilation passes.
Note that the implied value copy created by return v; is elided in later C++ standards.
For example i have code such as below
//g++ 5.4.0
#include <iostream>
struct data
{
int n;
data()
{
std::cout << "data()\n";
}
data(const data&)
{
std::cout << "data(const data&)\n";
}
data(data&&)
{
std::cout << "data(data&&)\n";
}
};
class container
{
data d;
public:
data getData()
{
return std::move(d);
}
};
int main()
{
container c;
data result = c.getData();
}
And output is:
data()
data(data&&)
I don't understand how it works. I have not declared return type as data&&, but move constructor works fine for result. Yes, code is std::move(d) but return type is not data&&. So, how does it work?
This answer changes in c++17.
data getData()
{
return std::move(d);
}
This method moves d into its return value.
data x = foo.getData();
this one constructs x from the return value of getData. However the C++ standard encourages and permits this construction to be elided if getData returns a prvalue (a value type that matches). Elision means that the identity and lifetime of the return value and x are merged. Only one object exists, not two.
This permits skipping side effects, like print statements in move constructors.
So d is the object moved from, and that move directly constructs x.
If you change getData to return data&&, now no move is done withingetData but one is done outside when you construct x.
In c++17 the return value of getData is never an object, it is a prvalue, and prvalues in c++17 are more like instructions to create objects. In effect elision is no longer optional.
If the return type is set to data (as in your case), then the returned object is a prvalue.
If the return type is set to data&&, then the returned object is an xrvalue.
In either case, the returned object is an rvalue, and result's move constructor will be called.
See also: http://stackoverflow.com/a/10159163/4509057
As per my understanding below code should call move constructor of Test class since this function is returning by value which means expression GetTestObj() should be rvalue and xvalues are implicitly moved but why this code is calling copy constructor ?
class Test
{
public:
Test()
{
}
Test(const Test& arg)
{
std::cout<<"Copy Constructor Called..."<<std::endl;
}
Test(Test&& arg)
{
std::cout<<"Move Constructor Called..."<<std::endl;
}
};
Test GetMyTestObj()
{
Test *ptr = new Test();
return *ptr;
}
Test dummy = GetMyTestObj(); //Copy Constructor Called...
In your code there is actually one copy from *ptr into the return value and one move from GetMyTestObj() to dummy. However, the compiler elides the move, so you won't see it traced. If you pass -fno-elide-constructors to GCC or Clang then you should see the copy and the move (demo).
If you want the construction of the return value to a move, you need to use std::move:
Test GetMyTestObj()
{
Test *ptr = new Test();
return std::move(*ptr);
}
However, there's really no need for dynamic allocation in this instance; it's inefficient and leaks memory with your implementation. You should just use an automatic variable:
Test GetMyTestObj()
{
Test test;
//I assume you're doing something else here
return test;
}
With the above code, the compiler can actually elide both constructions.
If you're doing nothing else in that function, you should just construct dummy directly:
Test dummy{};
value is copied not here (no constructor is called due to copy elision):
Test dummy = GetMyTestObj();
but here:
return *ptr;
because function has to make rvalue object from lvalue reference. Basically, GetMyTestObj() function in this case is equivalent to:
Test *ptr = new Test();
Test returnValue(*ptr);
return returnValue;
which means expression GetTestObj() should be rvalue and xvalues are implicitly moved
Firstly, answer your question directly, GetTestObj() is a prvalue.
a function call or an overloaded operator expression of non-reference return type, such as str.substr(1, 2), str1 + str2, or it++;
The point is that copy/move operation is needed for return *ptr;; ptr is a named variable, which is a lvalue. *ptr is lvalue too, it can't be moved.
You could use std::move explicitly to make it a xvalue to be movable:
return std::move(*ptr);
I have looked at different sources with regard to the internal implementation of auto_ptr<> and auto_ptr_ref<>. I have this question that I couldn't figure out why.
.... When returning a 'auto_ptr' from a function, the compiler finds that there is no suitable ctor to copy construct the returned object. But there is conversion to 'auto_ptr_ref' and ctor taking an 'auto_ptr_ref' constructing an 'auto_ptr'. Thus, the compiler creates an 'auto_ptr_ref' which basically just holds a reference to the original 'auto_ptr' and then constructs an 'auto_ptr' from this object. That's all (well, when returning an object, the compiler goes through this process normally twice because the returned value is copied somewhere but this does not change the process)....
(Reference http://www.josuttis.com/libbook/auto_ptr.html)
In this example, I emulate the implementation of auto_ptr<> and auto_ptr_ref<> and is able to generate results showing that compiler indeed goes through the process twice
The example has these basic traits:
1) A's copy constructor does NOT take const reference.
2) A has conversion operator B
3) A has constructor A(B);
class B {
};
class A {
public:
A () {
printf("A default constructor() # %p\r\n", this);
}
A(B) {
printf("constructor(B) # %p\r\n", this);
}
A (A &a) {
printf("copy constructor(non-const) # %p\r\n", this);
}
operator B() {
printf("A convertion constructor(B) # %p\r\n", this);
return B();
}
};
A foo()
{
return A();
}
int main()
{
A a(foo());
}
So when A a(foo())) is executed
1) foo() generates temporary object X
2) X is converted to type B
3) constructor A(B) is used to construct object a
This is output:
A default constructor() # 0xbfea340f
A convertion constructor(B) # 0xbfea340f
constructor(B) # 0xbfea344f
A convertion constructor(B) # 0xbfea344f
constructor(B) # 0xbfea344e
We can see that compiler wen through the conversion-construct steps 2&3 twice.
Why is that?
If you are calling a function which returns a class type, basically the following happens:
On the call, the calling function reserves some space for the temporary return value on the stack (it has to be done by the calling function because anything the called function allocates on the stack gets deallocated as soon as the function returns). It passes the address of that space to the called function.
On executing the return statement, the called function constructs the return value from the argument given to the return statement into the space provided by the calling function. In your case, that argument is the temporary A value.
After the function returns, the caller uses the temporary value the called function constructed to do whatever the code demands. In your case, you use it to construct a local variable from it.
So you construct a new object of type A from an existing one twice: First, to construct the temporary return value (whose life time persists after the function foo returns, until the end of the declaration) from the explicitly generated temporary in the return statement (whole lifetime ends on the end of the full expression, that is in this case equivalent to on return from foo). And second, to initialize the local variable a from the temporary returned by foo.
Of course, due to no appropriate copy constructor being available, in both cases you go through the B conversions. This works because the return does a direct initialization, and for a you explicitly coded such a direct initialization.
Class A is being created 3 times. Once as a temporary, and copied twice. Other compilers might return different results, based on their optimization settings.
return A() creates a temporary A, and then copies it to the returned A This first copy is the first time that you see steps 2 and 3.
Then A a(foo()); copies the return from foo() into the variable in main. Triggering steps 2 and 3 again.
This page says a strange thing :-
The temporaries are created only if your program does not copy the return value to an object and example given is
UDT Func1(); // Declare a function that returns a user-defined type.
...
Func1(); // Call Func1, but discard return value.
// A temporary object is created to store the return
// value
but if i have done :-
UDT obj=Fuct1;
It appears to me that it will also create a temporary as follow:-
Func() constructs a local object. Next, this local object is copy-constructed on the caller's stack, making a temporary object that is used as the argument of obj's copy-constructor.
Am I wrong?
Is this has something to do with copy elision?
The page you cite it a description of the behavior of a specific
compiler. Formally: the return value is always a temporary. In
contexts where that temporary is used as the argument of a copy
constructor (the object is copied), the standard gives explicit
authorization for the compiler to elide the copy, “merging”
the temporary with the named variable it is initializing. All the
sentence you quote is saying is that this specific compiler always does
his optimization (as do most other compilers).
This page is Microsoft specific. It's true that the standard permits to do two, one or zero calls to the copy constructor during function return (this is called copy elision). In fact one call is always sufficient.
Suppose you write:
A f(int x) {
return A(x);
}
void g() {
A r = f(10);
}
The way MSVC implements this is:
void f_impl(A* r, int x) {
new((void*)r) A(x); // construct the return value into r
}
void g_impl() {
A r = __uninitialized__;
f_impl(&r, 10);
}
Here you see zero calls to the copy constructor and no temporaries.
If you call f like this:
void g() {
f(10);
}
Then the compiler still needs to construct the return value somewhere, so it creates a temporary:
void g_impl() {
A r = __uninitialized__;
f_impl(&r, 10);
r.~A(); // destruct temporary
}
When it calls the copy constructor? In the implementation of f when it can't know which f's local will be returned. E.g. this:
A f(int x)
{
A r1;
A r2;
// ...do something complicated modifying both r1 and r2...
if(x)
return r1;
// ...do something complicated...
return r2;
}
Is translated to something like this:
void f_impl(A* r, int x)
{
A r1;
A r2;
// ...do something complicated modifying both r1 and r2...
if(x)
{
new((void*)r) A(r1); // copy construct r1
return;
}
// ...do something complicated...
new((void*)r) A(r2); // copy construct r2
}
The return value is always a temporary. In the second case, a copy of that temporary (move in C++11) is made if copy elision cannot occur.