Reputation: 2845
Class Plus inherits from class Expression.
class Expression
{
public:
virtual Expression* clone() const = 0;
};
class Plus : public Expression
{
public:
Plus( Expression* lhs, Expression* rhs ) :Expression( lhs, rhs) {};
Plus* clone() const;
};
I'm implementing a copy
function. The current implementation will leak memory if one of the clone
s or the Plus
fails.
Plus* Plus::clone() const {
return new Plus(tree_left->clone(), tree_right->clone());
}
and I think something like this would solve the problem:
Plus* Plus::clone() const {
Expression *tree_left_clone = nullptr;
Expression *tree_right_clone = nullptr;
Expression *plus_clone = nullptr;
try {
tree_left_clone = tree_left->clone();
tree_right_clone = tree_right->clone()
plus_clone = new Plus( tree_left_clone, tree_right_clone );
} catch (const bad_alloc& e ) {
delete tree_left_clone;
delete tree_right_clone;
delete plus_clone;
}
return plus_clone;
}
But there's a lot of similar operators including Minus, Times, Divided, Power etc. And I'd have to duplicate clone
for all of them. Is there a way to put this code in Expression
?
The problem I'm having is with the line in clone
containing new Plus
.
Upvotes: 2
Views: 83
Reputation: 44268
Use smart pointers instead of raw ones and your code will not leak:
class Expression;
typedef std::shared_ptr<Expression> ExpressionPtr;
class Expression
{
public:
virtual ExpressionPtr clone() const = 0;
};
class Plus : public Expression
{
public:
Plus( ExpressionPtr lhs, ExpressionPtr rhs ) :Expression( lhs, rhs) {};
ExpressionPtr clone() const;
};
ExpressionPtr Plus::clone() const {
return std::make_shared<Plus>( tree_left->clone(), tree_right->clone() );
}
You can use boost::shared_ptr if c++11 is not available.
Upvotes: 1
Reputation: 56883
That's what smart pointers are for. You could change the constructor to receive a std::unique_ptr
:
Plus( std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs )
: Expression( lhs.release(), rhs.release() ) {}
and call it like this:
Plus* Plus::clone() const {
std::unique_ptr<Expression> lhs( tree_left->clone() );
std::unique_ptr<Expression> rhs( tree_right->clone() );
return new Plus( std::move(lhs), std::move(rhs) );
}
But that should only be the beginning. You should also consider storing the pointers as std::unique_ptr
and avoid plain pointers as much as possible.
Upvotes: 1
Reputation: 661
Try something like that:
Plus* Plus::clone() const {
auto_ptr<Expression> tree_left_clone(tree_left->clone());
auto_ptr<Expression> tree_right_clone(tree_right->clone());
return new Plus(tree_left_clone.release(), tree_right_clone.release());
}
Upvotes: 1