0

I have this code ...

#include <stdio.h>
#include <stdlib.h>

class Foo{
public:
    int *a;
    Foo(int n);
    ~Foo();
    Foo* add(int n);
    void print();
};

Foo::Foo(int n){
    a=(int*)malloc(sizeof(int));
    *a=n;
}

Foo::~Foo(){
    printf("destructor called\n");
    free(a);
}

Foo* Foo::add(int n){
    return new Foo(*a+n);
}

void Foo::print(){
    printf("foo is =%i\n",*a);
}

int main(){
    Foo* bar = new Foo(1);
    delete bar;
    bar = new Foo(1);
    bar->add(1)->print();
}

The output is:

destructor called
foo is =2

The problem is that the destructor is called only once, and the address returned by add() is lost. I can only destruct it if I first save it to a variable and then call the destructor on it, like this:

Foo* temp = bar->add(1);
temp->print();
delete temp;

But I think this looks a bit messy, since I will use this new instance only once.

So my question is, is there a way to call the destructor of the returned object of a method if it is dereferenced but not assigned to any variable? So that the destructor in this code gets called correctly?

bar->add(1)->print();
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620

2 Answers2

1

You want to use std::unique_ptr:

class Foo{
public:
    std::unique_ptr<int> a;
    Foo(int n);
    ~Foo();
    std::unique_ptr<Foo> add(int n);
    void print();
};

Foo::Foo(int n){
    a = std::make_unique(n);
}
Foo::~Foo(){
    printf("destructor called\n");
}
std::unique_ptr<Foo> Foo::add(int n){
    return std::make_unique<Foo>(*a+n);
}
void Foo::print(){
    printf("foo is =%i\n",*a);
}
int main(){
    auto bar= std::make_unique<Foo>(1);
    bar=std::make_unique<Foo>(1);
    bar->add(1)->print();
}
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
Chris Dodd
  • 101,438
  • 11
  • 111
  • 197
1

Chris's answer addresses the particular example you provided.

But, there is no reason to use pointers in that example at all. The code can be simplified to this:

#include <iostream>

class Foo{
public:
    int a;

    Foo(int n);
    ~Foo();

    Foo add(int n);
    void print();
};

Foo::Foo(int n){
    a = n;
}

Foo::~Foo(){
    std::cout << "destructor called" << std::endl;
}

Foo Foo::add(int n){
    return Foo(a + n);
}

void Foo::print(){
    std::cout << "foo is =" << a << std::endl;
}

int main(){
    { Foo bar(1); }
    Foo bar(1);
    bar.add(1).print();
}
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620