| Overview | Group | Tree | Graph | Deprecated | Index | Concepts |
For most Concert applications, you can simply create the extractable objects that you need to build your model, then let their destructors manage the subsequent deletions. However, when memory use is critical to your application, you may need to take control of the deletion of extractable objects. In such cases, you will need a deeper understanding of how IBM® ILOG® Concert Technology creates and maintains extractable objects. The following guidelines, along with the concept Deletion of Extractable Objects, should help.
1. An expression
(that is, an instance of the class
IloExpr or its superclasses
IloNumExpr and
IloNumExprArg)
is passed by value to an extractable object (an instance of
the class IloExtractable).
Therefore, you
can delete the original expression after passing it by value without
affecting the extractable object that received it.
All copies by value are deep copies, not shallow copies.
More generally, if you have multiple handles passed to Concert objects
pointing to an instance of
IloExpr,
and you call a method that modifies one of those handles,
Concert Technology performs a lazy copy.
In other words, it first copies the implementation
object for the handle you are modifying and then makes the modification.
The other handles pointing to the original implementation object remain
unchanged, and your modification has no impact on them.
Lazy copying does not apply to other Concert Technology objects. In general, it is recommended that you avoid using multiple handles to the same object if you do not feel comfortable with lazy copying.
2. A variable (that is, an instance of
IloNumVar,
IloIntVar, or
IloBoolVar)
is passed by reference to an extractable object.
Therefore, when your Concert application is in linear deleter mode,
deleting a variable will remove it from any extractables that received it.
3. An extractable object is passed by reference
to a logical constraint
(such as IloIfThen)
or to a nonlinear expression (such as IloMax).
Therefore, you
should not delete the original expression after passing it to such functions
unless you have finished with the associated model.
Here are some examples to consider in light of these guidelines. The first example illustrates guidelines 2 and 3.
IloEnv env;
IloNumVar x(env, 0, IloInfinity, "X");
IloNumVar y(env, 0, IloInfinity, "Y");
IloNumVar z(env, 0, IloInfinity, "Z");
IloExpr e = x + y;
IloConstraint c1 = (e <= z);
IloConstraint c2 = (e >= z);
IloConstraint c3 = IloIfThen(env, c1, c2);
e.end(); // OK; c1 and c2 use copies of e;
c1.end(); // BAD IDEA; c3 still references c1
IloModel m(env);
m.add (c3); // c3 is not correctly represented in m.
In that example, since c1 is passed by reference, the
call to c1.end raises errors. In contrast, the call to
e.end causes no harm because e is passed
by value.
The following example illustrates guidelines 1 and 2.
IloEnv env;
IloModel model(env);
IloNumVar y(env, 0, 10, "y");
#ifdef WILLDELETE
IloNumVar y2 = y; // second handle pointing to implementation of y
#else
IloExpr y2 = y; // first handle pointing to expression 1*y
#endif
IloConstraint cst = y2 <= 6;
model.add(cst);
y2.end();
When y2 is an instance of the class IloNumVar,
the call to y2.and will remove y2 from the constraint
cst, according to guideline 2.
When y2 is an expression, it will be passed by value to the
constraint cst, according to guideline 1.
Hence, the call to y2.end will leave cst
untouched.
While a thorough understanding of these conventions provides you with complete control over management of the extractable objects in your application, in general, you should simply avoid creating extra handles to extractable objects that can result in unexpected behavior.
In light of that observation, the previous example can be simplified to the following lines:
IloEnv env;
IloModel model(env);
IloNumVar y(env, 0, 10, "y");
IloConstraint cst = y <= 6;
model.add(cst);