Reputation: 51
I have this:
struct Point
{
size_t x;
size_t y;
~Point()
{
std::cout << "Destro" << "\n";
}
};
const Point& getPoint()
{
return { 100, 120 };
}
int main()
{
Point p = getPoint();
std::cout << "Exit" << "\n";
}
and the result is
Destro
Exit
Destro
I'm basically trying to make the getPoint
method not have to copy the Point
class.
Here is what's happening so far:
How can I make it so that Point is only destroyed once?
Upvotes: 1
Views: 94
Reputation: 7905
Here's an example of what it looks like you're trying to achieve...
#include <iostream>
struct Point {
size_t x;
size_t y;
~Point() { std::cout << "Destructor called\n"; }
// Explicitly deleting the Copy Constructor only to illustrate a point.
Point(const Point& other) = delete;
};
const Point makePoint(size_t a, size_t b) {
return Point{ a, b };
}
int main() {
Point a = makePoint(3, 5);
std::cout << a.x << ',' << a.y << '\n';
}
Output:
3,5
Destructor called
If you noticed, I explicitly deleted the Copy Constructor
and left the Assignment Operator
undeclared so that it will use the default. The struct is still using the default constructor and I didn't define a User Defined
constructor.
In makePoint()
I added two parameters/arguments to the function so that the user can set any values to the Point object. The function is returning a const Type
object. The return statement in the function is using:
return Point{a, b};
instead of
return Point(a, b);
The latter will fail to compile because there is no user-defined constructor. However, the former works because I'm using brace-initialization
. This will allow construction of the object on return instead of creating a temporary on the stack frame of the function and copying that temporary as its return value. This is a form of Copy Elision.
Now, if you want to be able to copy
this object, you can remove the deleted constructor
and allow the class to use its default copy constructor. The semantics of the Copy Elision will still work.
This will have the same exact results. I showed the explicit deletion of the Copy Constructor to initially prevent any Copying semantics. Then explained how the code works so you can take the original above and remove the line for the deleted copy constructor and it will still work the same:
struct Point {
size_t x;
size_t y;
~Point() { std::cout << "Destructor called\n"; }
};
const Point makePoint(size_t a, size_t b) {
return Point{ a, b };
}
The functionality or behind the scenes magic is happening within the function makePoint()
and that it returns a const
object and uses brace-initialization
of the class.
Upvotes: 0
Reputation: 180500
You need to return by value instead of reference. Using
Point getPoint()
{
return { 100, 120 };
}
Allows C++17's guaranteed copy elision to kick in which causes Point p = getPoint();
to act as if it was Point p{ 100, 120 };
Side note: Never, Never, Never, return a function local object by reference. That object will be destroyed at the end of the function leaving you with a dangling reference and using that is undefined behavior.
Upvotes: 6