0

Consider C++ code as below:

struct V {
  int s;
  V(int s): s(s) {}
  ~V() { cout << "Destructor\n"; }
};

V f() {
  V x(2);
  return x;
}

int main(){
  V a = f();
  cout << "Function End\n";
  return 0;
}

The execution result shows that the destructor is called only once.

Function End
Destructor

However, if I add a meaningless if statement as below, the destructor is called twice.

V f() {
  if(false) return V(3);
  V x(2);
  return x;
}
Destructor
Function End
Destructor

Why can this happen? Is there some points to avoid calling destructor twice?

Risebbit
  • 13
  • 1
  • 2
    Print the value of `this`, not just the word "Destructor". Then you will see you are destroying another object (which you are not tracking). – PaulMcKenzie Mar 06 '22 at 17:29
  • You might get a better picture of what is happening if you added some noisey constructors. – Taekahn Mar 06 '22 at 17:30
  • 2
    Also have a look at RVO https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization – ACB Mar 06 '22 at 17:30
  • Why do you want to avoid the destructor being called twice? That shouldn't normally matter to you. – user17732522 Mar 06 '22 at 17:32
  • I originally wrote a class which dynamically allocated memory instead of `V` and I had a problem of double free. I thought this problem is caused by the destructor being called twice. Now I figured out the reason for double free is the inappropriate copy constructor. – Risebbit Mar 06 '22 at 18:26

1 Answers1

1

In the first example, NRVO (Named Return Value Optimization) may kick in and elide the copy in return x;.

When you have two exit paths, not returning the same variable, NRVO is less likely to kick in and you'll actually get a copy, even though if(false) is never going to be true.

The below would most likely also elide the copy because x is returned in all paths that leads to return.

V f() {
    V x(2);
    if (false) x = V(3);
    return x;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108