I've been playing around with the Compiler Explorer recently. I loaded one of their examples that takes pointer parameters and changed it to instead take unique_ptr parameters. But I noticed that in the output assembly, calls to operator delete were conspicuously absent. I'm curious if anyone knows why.
Here's an example you can paste into the explorer. Be sure to also put -O3
in the compiler options.
#include <memory>
using std::unique_ptr;
void maxArray(unique_ptr<double[]> x, unique_ptr<double[]> y) {
for (int i = 0; i < 65536; i++) {
if (y[i] > x[i]) x[i] = y[i];
}
}
EDIT: Also for comparison, if instead I paste in one of the code examples from cppreference, then I do get operator delete in the output.
#include <iostream>
#include <memory>
struct Foo
{
Foo() { std::cout << "Foo::Foo\n"; }
~Foo() { std::cout << "Foo::~Foo\n"; }
void bar() { std::cout << "Foo::bar\n"; }
};
void f(const Foo &)
{
std::cout << "f(const Foo&)\n";
}
int main()
{
std::unique_ptr<Foo> p1(new Foo); // p1 owns Foo
if (p1) p1->bar();
{
std::unique_ptr<Foo> p2(std::move(p1)); // now p2 owns Foo
f(*p2);
p1 = std::move(p2); // ownership returns to p1
std::cout << "destroying p2...\n";
}
if (p1) p1->bar();
// Foo instance is destroyed when p1 goes out of scope
}
EDIT: +1 to krzaq. It's the caller, not the callee, that constructs and destroys parameters.
This problem boils down to:
void foo(unique_ptr<int>)
{
}
foo(make_unique<int>());
Where does foo
's parameter live?
The following standardese is pertinent to this question:
N4140 §5.2.2 [expr.call]/4
The lifetime of a parameter ends when the function in which it is defined returns. The initialization and destruction of each parameter occurs within the context of the calling function.
In other words: your maxArray
is not required to be responsible for calling x
and y
's destructors; gcc implements it this way, and that's why there are no delete
calls in the codegen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With