This class is experimental and subject to change.
Normally all term references in a scope are discarded 
together or all term references created after a specific one are 
reclaimed using PlTerm::reset_term_refs(). A PlTermScoped 
object is the same as a PlTerm object except that
PL_free_term_ref() is called on its wrapped term when the object 
goes out of scope. This shrinks the current foreign frame if the term is 
the last one in the frame and otherwise it marks it for reuse.
Here is an example, where PlTermScoped is inside a 
for-loop. If PlTerm were used instead, the stack would grow 
by the number of items in the array; PlTermScoped ensures 
that stack doesn't grow.10Assuming 
that unify_atom_list() is called from a predicate implementation, 
if PlTerm were used instead of PlTermCopy, all 
the created terms would be discarded when the Prolog stack frame is 
unwound; the use of PlTermScoped reuses the terms in that 
stack frame. A slightly more effiicient way of preventing 
the Prolog stack from growing is to use PlTerm::put_term() 
to reuse a term reference; but that is more difficult to understand and 
also more error-prone.
bool
unify_atom_list(const std::vector<std::string>& array, PlTerm list)
{ PlTermScoped tail(list); // calls PL_copy_term_ref() to copy `list`
  for( auto item : array )
  { PlTermScoped head; // var term
    PlCheckFail(tail.unify_list(head, tail));
    PlCheckFail(head.unify_chars(PL_ATOM, item));
  }
  return tail.unify_nil();
}
The design of PlTermScoped is modeled on
std::unique_ptr11unique_ptr 
was originally called scoped_ptr in the Boost libraries, 
but the name was changed to contrast with std::shared_ptr, 
which is reference-counted. and uses move semantics 
to ensure safety.12Move 
semantics are a relatively new feature in C++ and can be a bit 
difficult to understand. Roughly speaking, a move is a copies 
the object and then calls its destructor, so that any further use of the 
object is an error. If an object defines move methods or constructors, 
it can optimize this operation, and also can catch certain kinds of 
errors at compile time.
A PlTermScoped object can be created either with or 
without a wrapped term - the PlTermScoped::reset() 
method sets (or nulls) the wrapped term. A PlTermScoped 
object cannot be copied or passed as a value to a function; the PlTermScoped::release() 
method returns the wrapped term and resets the PlTermScoped 
object so that any further use of the PlTermScoped object 
is an error.
As shown in the example above, PlTermScoped can be used 
instead of PlTerm, in places where a loop would otherwise 
cause the stack to grow. There are limitations on the operations that 
are allowed on a PlTermScoped object; in particular, a
PlTermScoped object cannot be copied and cannot be 
implicitly converted to a Plterm.
The PlTermScoped constructors always create a new term 
ref, by calling either PL_new_term_ref() or PL_copy_term_ref(). 
If you try to copy or create a PlTermScoped object from 
another
PlTermScoped object, you will get a compile-time error; you 
can set the value from a PlTerm object, which can be 
obtained by calling PlTermScoped::release().
The methods derived from the PL_put_*() and PL_cons_*() functions 
should not be used with a PlTermScoped object. If you need 
to use these, you can use PlTermScoped::get() 
to get a PlTerm, for which a put_*() method can be used.
To copy a PlTermScoped object or to pass it as a value 
in a function call, use the PlTermScoped::release() 
method or std::move():
PlTermScoped ts(...); PlTerm t; // Copy to a PlTerm: t = ts.release(); // or: t = std::move(ts); // Pass as a value to a function: foo(ts.release()); // or: foo(std::move(ts); // Copy to a PlTermScoped: PlTermScoped ts2; ts2.reset(ts.release()); // or: ts2.reset(std::move(ts));
The methods are (in addition to, or overriding the methods in PlTerm):
PlTermScoped, use PlTermScoped::release() 
to convert it to a PlTerm.PlTerm. This is typically used 
when calling a function that expects a PlTerm object and 
which will not call
PlTerm::free_term_ref() 
on it.t2.reset(t.release()) 
to copy a
PlTermScoped; this can also be written
t2=std::move(t).PlTermScoped objects’wrapped terms.